使用SWI Prolog,有一個謂詞可以找到名爲nth1的列表中的第n個項目。我想實現我自己的謂詞版本,但是如果您查看列表(第nth1)代碼,SWI會非常複雜。有沒有更簡單的方法呢?Prolog中的簡單nth1謂詞
謝謝:)。
使用SWI Prolog,有一個謂詞可以找到名爲nth1的列表中的第n個項目。我想實現我自己的謂詞版本,但是如果您查看列表(第nth1)代碼,SWI會非常複雜。有沒有更簡單的方法呢?Prolog中的簡單nth1謂詞
謝謝:)。
的SWI代碼是有點複雜,因爲謂詞可以用來從一個變量指標產生:
?- nth1(Idx,[a,b,c],X).
Idx = 1,
X = a ;
Idx = 2,
X = b ;
Idx = 3,
X = c ;
false.
如果你不希望這樣的行爲,nth1/3
可以很容易地在nth0
方面實現的:
nth1(Idx,List,X) :-
Idx0 is Idx-1,
nth0(Idx0,List,X).
編輯:它也可以在短短的幾行代碼,而不nth0
做:
nth1(1,[X|_],X) :- !.
nth1(Idx,[_|List],X) :-
Idx > 1,
Idx1 is Idx-1,
nth1(Idx1,List,X).
謝謝larsmans,我不想使用任何第n個謂詞,我已經發布了我的解決方案,您怎麼看?感謝這篇文章。 – ale 2010-11-21 12:35:36
@shuyin,我也發佈了一個'nnth0'的解決方案。 – 2010-11-21 14:40:45
我不是故意矛盾或者讓別人來做我的工作,我只是想要一些建議,抱歉不清楚。
我已經自己實現它,但你們可能會建議改進或更好的方法嗎?我經常在Prolog中發現自己正在寫一個謂詞,用一個計數器或一組計數器來得到一個謂詞,用較少的參數來調用具有額外參數的子句。這通常會導致生成相當多的代碼。無論如何,這是我剛纔的實現:
item_at(N, L, Item) :-
item_at(N, 0, L, Item).
item_at(N, Count, [H|_], Item) :-
CountNew is Count + 1,
CountNew = N,
Item = H.
item_at(N, Count, [_|T], Item) :-
CountNew is Count + 1,
item_at(N, CountNew, T, Item).
有什麼意見?謝謝 :)。用法:
?- item_at(3,[a,b,c,d,e],Item).
Item = c ;
+1,這個版本是相當一般的(儘管它可能會在回溯/生成時進入無限遞歸)。一個建議,第二個條款可以更短:'item_at(N,Count,[H | _],H): - N是Count +1 1. – 2010-11-21 14:44:15
謝謝larsmans,這是一個很好的改進,非常感謝: )。測試和工作,我可以看到如何:)。 – ale 2010-11-21 15:07:46
考慮使用有限域約束一般(可逆)整數運算:
:- use_module(library(clpfd)).
nth1(1, [E|_], E).
nth1(N, [_|Xs], E) :-
N #> 1,
N #= N1 + 1,
nth1(N1, Xs, E).
這與shuyin的解決方案有相同的無限遞歸問題,效率不高。 +1雖然優雅。 (但是,爲了提高效率,我會添加一個約束'N#> 1',並且可能需要剪切。) – 2010-11-21 15:52:20
是的,將N#> 1添加到第二個子句中是個好主意,我認爲這會消除無限遞歸意思是說,即對於像? - nth1(3,Es,X)這樣的查詢?但是,如果在第一個子句中添加一個剪切,將會消除有效的解決方案,例如對於最一般的查詢? - nth1(N,Ls,E),從而使謂詞不完整。 – mat 2010-11-21 17:08:12
你是對的。 – 2010-11-22 10:41:03
澄清你所說的「簡單」?更少的代碼行?您可以移除例如「列表:nth0_det(3,[_,_,_,A | _],A): - !。」否則,簡單化的唯一方法是使其不那麼一般。這是你想要的嗎? – Kaarel 2010-11-21 20:57:02