Prolog 序言-检查是否正确放置

Prolog 序言-检查是否正确放置,prolog,puzzle,clpfd,Prolog,Puzzle,Clpfd,我有一个拼图,是一个3*3的网格,里面有数字1-8,有一个空白点(0),我可以移动。这是谜题的最终状态: 1 2 3 8 0 4 7 6 5 整个“状态”由状态(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的输

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

1 2 3 
8 0 4 
7 6 5
整个“状态”由状态(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的输出?任何帮助都将不胜感激。谢谢。

在Prolog中有一个简短的表达方式,但它需要

:-使用_模块(库(clpfd))。
h(状态,Z):-
州=。。[state | Pos],
地图列表(相等,位置[0,1,2,3,8,0,4,7,6,5],等式),
求和(等式,#=,Z)。
相等(X,Y,E):-
E#(X#=Y)。

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

这看起来很简单

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对元素进行非确定性访问):

:- [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).
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).