2011-12-02 22 views
3

我試着寫在序言 adjacent(X,Y,Zs)一個規則,如true如果XY在列表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
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)會做同樣的(但請記住,這個謂詞的語義是Y如下列表X,不只是簡單的以任意順序相鄰)。

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

+0

沒有爲'只有一個解決方案nextto(X,Y,[1,2])'但是你的定義'毗鄰(X,Y,[1,2])'有兩個。 – false

+0

@false op要求* adjacency *無論排序如何,這就是爲什麼我的謂詞給出了兩個答案......'nextto'在'X'之後統一'Y',我認爲這很明顯,不值得明確表示。 – fortran

+0

謝謝您的澄清,@fortran。顯然,這並不明顯。 – false

1

你的程序的行爲是相當複雜的。該錯誤位於子列表/ 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的正確道路。掌握內建函數的使用是正確的,在簡單的定義後面隱藏複雜的行爲。

2

採用DCG中都代表着最圖形化的方式可能的問題:

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

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

編輯:多虧@ FORTRAN的評論,另一種定義可能是:

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