我对prolog非常陌生,我想编写一个程序,该程序将数字增加或减少1,然后对结果进行相同的操作三次。我期望的结果是一系列三个数字,代表了所有可能的结果。例如,如果我给它编号4,我可以得到
567 565 545 543 456 454 434 432
更正 567 565 545 543 345 343 323 321
我认为对于某些组合或递归以及or条件而言,这是有意义的。
aos(_,3):- write('end').
aos(J,X):- (N is J+1, write(N),Y is X+1,aos(N,Y));
(N is J-1, write(N), Y is X+1,aos(N,Y)).
上面是我的数据库文件,下面是我运行的查询。
aos(4,0).
我将得到的输出是
567end
,然后当我单击下一步时,它将继续输出89101112...
我不明白为什么会这样,我将不胜感激。
答案 0 :(得分:1)
问题在于,当您要求下一个解决方案时,X会增加到4。递归仍在继续,但是由于X现在大于3,您的终端大小写将永远不匹配。
您可以这样看到自己:
?- spy(aos/2).
% Spy point on aos/2
true.
[debug] ?- aos(4,0).
* Call: (8) aos(4, 0) ? Options:
+: spy -: no spy
/c|e|r|f|u|a goal: find .: repeat find
a: abort A: alternatives
b: break c (ret, space): creep
[depth] d: depth e: exit
f: fail [ndepth] g: goals (backtrace)
h (?): help i: ignore
l: leap L: listing
n: no debug p: print
r: retry s: skip
u: up w: write
m: exception details
C: toggle show context
* Call: (8) aos(4, 0) ? creep
Call: (9) _850 is 4+1 ? creep
Exit: (9) 5 is 4+1 ? creep
Call: (9) write(5) ? creep
5
Exit: (9) write(5) ? creep
Call: (9) _856 is 0+1 ? creep
Exit: (9) 1 is 0+1 ? creep
* Call: (9) aos(5, 1) ? creep
Call: (10) _862 is 5+1 ? creep
Exit: (10) 6 is 5+1 ? creep
Call: (10) write(6) ? creep
6
Exit: (10) write(6) ? creep
Call: (10) _868 is 1+1 ? creep
Exit: (10) 2 is 1+1 ? creep
* Call: (10) aos(6, 2) ? creep
Call: (11) _874 is 6+1 ? creep
Exit: (11) 7 is 6+1 ? creep
Call: (11) write(7) ? creep
7
Exit: (11) write(7) ? creep
Call: (11) _880 is 2+1 ? creep
Exit: (11) 3 is 2+1 ? creep
* Call: (11) aos(7, 3) ? creep
Call: (12) write(end) ? creep
end
Exit: (12) write(end) ? creep
* Exit: (11) aos(7, 3) ? creep
* Exit: (10) aos(6, 2) ? creep
* Exit: (9) aos(5, 1) ? creep
* Exit: (8) aos(4, 0) ? Unknown option (h for help)
* Exit: (8) aos(4, 0) ? creep
true ;
* Redo: (11) aos(7, 3) ? creep
Call: (12) _886 is 7+1 ? creep
Exit: (12) 8 is 7+1 ? creep
Call: (12) write(8) ? creep
8
Exit: (12) write(8) ? creep
Call: (12) _892 is 3+1 ? creep
Exit: (12) 4 is 3+1 ? creep
* Call: (12) aos(8, 4) ? creep
Call: (13) _898 is 8+1 ? creep
Exit: (13) 9 is 8+1 ? creep
Call: (13) write(9) ? creep
9
问题在于,当您寻求其他解决方案时,Prolog的最后选择点是aos(7,3)之后最里面的一个。因此它将进入J = 7和X = 3的第二个分支。您可以这样解决此问题:
aos(_,3):- write('end').
aos(J,X):- X < 3, ((N is J+1, write(N),Y is X+1,aos(N,Y));
(N is J-1, write(N), Y is X+1,aos(N,Y))).
但是,这不会产生您想要的输出序列。您将获得567 5 45 3 345 3 23 1.我不完全确定要获得该输出序列需要做什么,但是我怀疑您需要将三个加法项组合在一起,并使用第二个变量将它们分散开,这导致你麻烦我可能会这样实现:
inc_or_dec(X, Y) :- succ(X, Y).
inc_or_dec(X, Y) :- succ(Y, X).
aos(N) :-
inc_or_dec(N , N1),
inc_or_dec(N1, N2),
inc_or_dec(N2, N3),
write(N1), write(N2), write(N3), write('end'), nl.
这对于Prolog来说更明显,在这里真正的选择点不在,即不在三个一组的单个数字之间。但是,这仍然不能完全满足您所需的顺序。您将获得567 565 545 543 345 343 323321。如果最初要获得4的解,则必须放宽约束并使X保持不变,但是如果这样做,您还将获得444和555.了解您要达到的目标可能会有所帮助,而不只是了解您如何实现的。