3

我正在尝试在 prolog 中编写规则 adjacent(X,Y,Zs),就true好像X并且Y在 list 中彼此相邻Zs

我目前有:

append([],L,L).
append([H|T],L,[H|LT]):-append(T,L,LT).
sublist(S,L):-append(_,S,P),append(P,_,L).
adjacent(X,Y,Zs):-sublist([X,Y],Zs).

测试:

1 ?- sublist([1,2],[1,2,3,4]).
true .

2 ?- sublist([1,3],[1,2,3,4,5]).
ERROR: Out of global stack
3 ?- 

你们有什么想法吗?提前致谢。

4

3 回答 3

4
adjacent(X,Y, [X,Y|_]).
adjacent(X,Y, [Y,X|_]). % remove this if you want just Y after X
adjacent(X,Y, [_|T]) :- adjacent(X,Y,T).

那应该工作。

此外,您在列表库中有一个谓词,nextto(?X, ?Y, ?List)它会做同样的事情(但请记住,这个谓词的语义是在列表YX,而不仅仅是以任何顺序相邻)。

http://www.swi-prolog.org/pldoc/doc_for?object=section%282,%27A.12%27,swi%28%27/doc/Manual/lists.html%27%29%29

于 2011-12-02T21:27:17.810 回答
2

使用 DCG 将以最直观的方式表示问题:

... --> [] | [_], ... .

adjacent(X,Y,Seq) :- phrase((...,[X,Y],...), Seq).

编辑:感谢@fortran 的评论,另一个定义可能是:

adjacent(X,Y,Seq) :- phrase((...,( [X,Y] | [Y,X] ),...), Seq).
于 2011-12-06T03:29:33.077 回答
1

你的程序的行为相当复杂。该错误在 sublist/2 中。

为了跟踪,我已将谓词重命名为在名称中添加 1,但它的定义是从您的代码中逐字获取的。

您可以看到对 append1(标记为 9,10,11,...)的调用逐渐扩展了未绑定的第一个参数。

?- trace,sublist1([1,3],[1,2,3,4]).
Call: (8) sublist1([1, 3], [1, 2, 3, 4]) ? creep
Call: (9) append1(_G377, [1, 3], _G379) ? creep
Exit: (9) append1([], [1, 3], [1, 3]) ? creep
Call: (9) append1([1, 3], _G378, [1, 2, 3, 4]) ? creep
Call: (10) append1([3], _G378, [2, 3, 4]) ? creep
Fail: (10) append1([3], _G378, [2, 3, 4]) ? creep
Fail: (9) append1([1, 3], _G378, [1, 2, 3, 4]) ? creep
Redo: (9) append1(_G377, [1, 3], _G379) ? creep
Call: (10) append1(_G374, [1, 3], _G377) ? creep
Exit: (10) append1([], [1, 3], [1, 3]) ? creep
Exit: (9) append1([_G373], [1, 3], [_G373, 1, 3]) ? creep
Call: (9) append1([_G373, 1, 3], _G384, [1, 2, 3, 4]) ? creep
Call: (10) append1([1, 3], _G384, [2, 3, 4]) ? creep
Fail: (10) append1([1, 3], _G384, [2, 3, 4]) ? creep
Fail: (9) append1([_G373, 1, 3], _G384, [1, 2, 3, 4]) ? creep
Redo: (10) append1(_G374, [1, 3], _G377) ? creep
Call: (11) append1(_G380, [1, 3], _G383) ? creep
Exit: (11) append1([], [1, 3], [1, 3]) ? creep
Exit: (10) append1([_G379], [1, 3], [_G379, 1, 3]) ? creep
Exit: (9) append1([_G373, _G379], [1, 3], [_G373, _G379, 1, 3]) ? creep
Call: (9) append1([_G373, _G379, 1, 3], _G390, [1, 2, 3, 4]) ? creep
Call: (10) append1([_G379, 1, 3], _G390, [2, 3, 4]) ? creep
Call: (11) append1([1, 3], _G390, [3, 4]) ? creep
Fail: (11) append1([1, 3], _G390, [3, 4]) ? creep
Fail: (10) append1([_G379, 1, 3], _G390, [2, 3, 4]) ? creep
Fail: (9) append1([_G373, _G379, 1, 3], _G390, [1, 2, 3, 4]) ? creep
Redo: (11) append1(_G380, [1, 3], _G383) ? creep
Call: (12) append1(_G386, [1, 3], _G389) ? creep
Exit: (12) append1([], [1, 3], [1, 3]) ? creep
Exit: (11) append1([_G385], [1, 3], [_G385, 1, 3]) ? creep
Exit: (10) append1([_G379, _G385], [1, 3], [_G379, _G385, 1, 3]) ? creep
Exit: (9) append1([_G373, _G379, _G385], [1, 3], [_G373, _G379, _G385, 1, 3]) ? creep
Call: (9) append1([_G373, _G379, _G385, 1, 3], _G396, [1, 2, 3, 4]) ? creep
...

无论如何,我认为你已经选择了正确的方式来学习 Prolog。掌握内置函数的用法是正确的,看似简单的定义背后往往隐藏着复杂的行为。

于 2011-12-02T23:39:20.743 回答