3

我有一个拼图,它是一个 3*3 的网格,里面有数字 1-8,有一个可以移动的空白点 (0)。这是拼图的最终状态:

1 2 3 
8 0 4 
7 6 5

通过横向阅读,整个“状态”由 state(1,2,3,8,0,4,7,6,5) 表示。我需要一个函数来检查哪些部分在正确的位置。

我有:

h(state(A,B,C,D,E,F,G,H,I),Z) :-

现在 Z 将是正确位置的件数。

A = 1
B = 2
C = 3
D = 8
E = 0
F = 4
G = 7
H = 6
I = 5

有什么简单的方法可以为 Z 提供输出吗?任何帮助,将不胜感激。谢谢。

4

3 回答 3

2

您确定不能将您的信息存储在列表中吗?如果您想要一种迭代它们的方法,这有点像在传统语言中使用数组而不是一堆变量的方式。

于 2011-11-05T13:53:34.343 回答
1

在 Prolog 中有一种简短的表达方式,但它需要CLP(FD)

:- use_module(library(clpfd)).

h(State, Z) :-
    State =.. [state | Pos],
    maplist(equal, Pos, [0,1,2,3,8,0,4,7,6,5], Eq),
    sum(Eq, #=, Z).

equal(X, Y, E) :-
    E #<==> (X #= Y).
于 2011-11-05T11:55:31.930 回答
0

这似乎很简单......

h(state(A,B,C,D,E,F,G,H,I),Z) :-
    count_matching([A,B,C,D,E,F,G,H,I], [1,2,3,8,0,4,7,6,5], 0, Z).

count_matching([], [], N, N).
count_matching([A|As], [B|Bs], N, M) :-
    (   A == B
    ->  T is N + 1
    ;   T is N
    ),
    count_matching(As, Bs, T, M).

SWI-Prolog 聚合库提供了另一种解决问题的简单方法:

:- [library(aggregate)].

h(state(A,B,C,D,E,F,G,H,I),Z) :-
    aggregate_all(count,
      (nth1(Index, [1,2,3,8,0,4,7,6,5], Cell),
       nth1(Index, [A,B,C,D,E,F,G,H,I], Cell)), Z).

使用 aggregate_all 太过分了:这里是一个使用相同模式的更简单的程序(通过 nth/3 对元素进行非确定性访问):

h(state(A,B,C,D,E,F,G,H,I),Z) :-
    findall(_,
      (nth1(Index, [1,2,3,8,0,4,7,6,5], Cell),
       nth1(Index, [A,B,C,D,E,F,G,H,I], Cell)), L),
    length(L, Z).
于 2011-11-05T15:50:19.227 回答