我正在尝试解决此Pebble Solitaire问题,这是我的代码的一部分:
% Base case
play(List, X) :-
count_pebbles(List, X).
%%%%%%%%%%%%%%
% JUMP RIGHT %
%%%%%%%%%%%%%%
% oo-XXXXXXXXX
play( [111, 111, 45|Tail], X) :-
play([45, 45, 111|Tail], X).
% Xoo-XXXXXXXX
play( [A, 111, 111, 45|Tail], X) :-
play([A, 45, 45, 111|Tail], X).
% XXoo-XXXXXXX
play( [A, B, 111, 111, 45|Tail], X) :-
play([A, B, 45, 45, 111|Tail], X).
% XXXoo-XXXXXX
play( [A, B, C, 111, 111, 45|Tail], X) :-
play([A, B, C, 45, 45, 111|Tail], X).
% XXXXoo-XXXXX
play( [A, B, C, D, 111, 111, 45|Tail], X) :-
play([A, B, C, D, 45, 45, 111|Tail], X).
% XXXXXoo-XXXX
play( [A, B, C, D, E, 111, 111, 45|Tail], X) :-
play([A, B, C, D, E, 45, 45, 111|Tail], X).
% XXXXXXoo-XXX
play( [A, B, C, D, E, F, 111, 111, 45|Tail], X) :-
play([A, B, C, D, E, F, 45, 45, 111|Tail], X).
% XXXXXXXoo-XX
play( [A, B, C, D, E, F, G, 111, 111, 45|Tail], X) :-
play([A, B, C, D, E, F, G, 45, 45, 111|Tail], X).
% XXXXXXXXoo-X
play( [A, B, C, D, E, F, G, H, 111, 111, 45|Tail], X) :-
play([A, B, C, D, E, F, G, H, 45, 45, 111|Tail], X).
% XXXXXXXXXoo-
play( [A, B, C, D, E, F, G, H, I, 111, 111, 45], X) :-
play([A, B, C, D, E, F, G, H, I, 45, 45, 111], X).
%%%%%%%%%%%%%
% JUMP LEFT %
%%%%%%%%%%%%%
% -ooXXXXXXXXX
play( [45, 111, 111|Tail]) :-
play([111, 45, 45|Tail]).
% X-ooXXXXXXXX
play( [A, 45, 111, 111|Tail]) :-
play([A, 111, 45, 45|Tail]).
% XX-ooXXXXXXX
play( [A, B, 45, 111, 111|Tail]) :-
play([A, B, 111, 45, 45|Tail]).
% XXX-ooXXXXXX
play( [A, B, C, 45, 111, 111|Tail]) :-
play([A, B, C, 111, 45, 45|Tail]).
% XXXX-ooXXXXX
play( [A, B, C, D, 45, 111, 111|Tail]) :-
play([A, B, C, D, 111, 45, 45|Tail]).
% XXXXX-ooXXXX
play( [A, B, C, D, E, 45, 111, 111|Tail]) :-
play([A, B, C, D, E, 111, 45, 45|Tail]).
% XXXXXX-ooXXX
play( [A, B, C, D, E, F, 45, 111, 111|Tail]) :-
play([A, B, C, D, E, F, 111, 45, 45|Tail]).
% XXXXXXX-ooXX
play( [A, B, C, D, E, F, G, 45, 111, 111|Tail]) :-
play([A, B, C, D, E, F, G, 111, 45, 45|Tail]).
% XXXXXXXX-ooX
play( [A, B, C, D, E, F, G, H, 45, 111, 111|Tail]) :-
play([A, B, C, D, E, F, G, H, 111, 45, 45|Tail]).
% XXXXXXXXX-oo
play( [A, B, C, D, E, F, G, H, I, 45, 111, 111]) :-
play([A, B, C, D, E, F, G, H, I, 111, 45, 45]).
是的,这太丑了。
然而,当我打电话给findall( Value, play(Game, Value), Values)
时,游戏只是45和111的任何序列(例如[45,111,45,45,45,45,111,111,111,45,45, 45]),值只与2个项目的列表统一(编辑:不是,它与更多项目统一,请参阅注释)。
根据我的理解,当我调用findall / 3时,它在基本情况谓词中找到一个解决方案(它只计算鹅卵石的数量并用X统一它),然后从另外20个中的任何一个解决方案玩谓词,然后......停止?
我需要它继续前进,直到找到所有解决方案。为什么它在2个解决方案后停止?我怎样才能继续?
答案 0 :(得分:3)
您的计划存在一些问题。你找到了一个。还有更多!
1mo作为惯例,省略属于同一谓词的子句之间的空行。这有助于避免您遇到的这些意外问题。
2do另一个有用的约定是避免使用ASCII码。而是使用chars(长度为1的原子),如下所示:
[45,111,45,45,45,45,111,111,111,45,45,45] % your example
[-,o,-,-,-,-,o,o,o,-,-,-] % using chars
"-o----ooo---" % :- set_prolog_flag(double_quotes, chars).
请注意,指令set_prolog_flag(double_quotes, chars)
仅影响双引号"strings"
的读取方式。它仍会为答案替换喷出实际字符:
?- L = "-o--".
L = [-,o,-,-].
要获得紧凑的答案,请使用use_module(library(double_quotes))
! (首先,只需将SWI的double_quotes.pl
下载到与Prolog文件相同的目录中,然后说:)
?- use_module(double_quotes).
true.
?- L = "-o--".
L = "-o--".
3tio这是一个重写:首先将谓词play/2
分成单个动作。将递归与其他代码混合通常非常麻烦。想象一下,递归谓词不会终止!无论如何,同时太多了。以下是我的看法:
:- set_prolog_flag(double_quotes,chars).
move(Xs0, Xs) :-
phrase( ( seq(Prefix), localmove ) , Xs0, Xs1),
phrase( seq(Prefix), Xs, Xs1).
localmove, "o--" --> "-oo".
localmove, "-oo" --> "oo-".
seq([]) --> [].
seq([E|Es]) --> [E], seq(Es).
?- move("-o----ooo---",S).
S = "-o---o--o---" ;
S = "-o----o-oo--" ;
false.
所以现在,我们只有一个动作。接下来,我们希望按顺序进行多次移动。为了确保我们不会进入周期,我将使用另一个示例中定义的closure0/3
。
?- S0 = "-o----ooo---", closure0(move, S0,S).
S0 = "-o----ooo---", S = S0
; S0 = "-o----ooo---", S = "-o---o--o---"
; S0 = "-o----ooo---", S = "-o----o-oo--"
; S0 = "-o----ooo---", S = "-o----oo----"
...
这些是许多中间步骤。是否会有多少或无限多?会有周期吗?我们可以盯着所有的答案,或让Prolog为我们思考:
?- S0 = "-o----ooo---", move(S0,S1), closure0(move, S1,S0).
% one move ahead, more moves, ^^ and back
false.
这失败了,因此没有回到原始状态的循环。我们能否一般证明这一点?对于所有可能的长度?直至N = 9
,我按预期失败了:
?- length(S0,9), move(S0,S1), closure0(move,S1,S0).
false.
让我重复一遍:这里,Prolog证明了所有可能有9个孔的电路板没有周期。当然有一个更简单的论点:一个移动移除一个卵石,另一个移动将鹅卵石移动到右边。但最后一个问题的要点是:Prolog确实通过立即考虑所有可能的主板 来证明这一点!