我需要找到一個列表中的第一個重複的值。序言:一是重複值
prep(3,[1,3,5,3,5]).
應該是真實的。
prep(5,[1,3,5,3,5]).
應該是假的。
我想檢查與當前值和先前列表成員平等,直到我找到了重複的,如果找到的話,會測試與X平等的,但我不知道該怎麼做的序言!
我感謝任何幫助!由於
我需要找到一個列表中的第一個重複的值。序言:一是重複值
prep(3,[1,3,5,3,5]).
應該是真實的。
prep(5,[1,3,5,3,5]).
應該是假的。
我想檢查與當前值和先前列表成員平等,直到我找到了重複的,如果找到的話,會測試與X平等的,但我不知道該怎麼做的序言!
我感謝任何幫助!由於
不知道這是功課/有限制上謂詞你被允許使用,不過這樣會序言做遞歸你。
它說..找到所有重複IE瀏覽器。哪裏有一個列表索引爲I1的項目,另一個爲I2,這樣它們的值都是相同的N,並且索引不相同,即不會將同一列表項視爲重複項。
這些重複項按照它們被發現的順序(從一開始至關重要)放入列表AllDups中,如果第一個重複項與M相匹配,則謂詞爲true,這是您正在檢查的值。
第一次嘗試:這工作,但效率非常低,大樓中所有的列表複製
prep(M, List) :-
findall(N,
(nth0(I1, List, N),
nth0(I2, List, N),
not(I1 =:= I2)),
AllDups),
nth1(1, AllDups, M).
?- prep(3,[1,3,5,3,5]).
true.
?- prep(5,[1,3,5,3,5]).
false.
即使你不允許的findall使用,它可以幫助你的工作怎麼辦呢「手動」。
第二次嘗試:這不起作用/回溯太遠產生假陽性
你甚至可以做到這一點沒有的findall - 使用nth0找到第一個重複的項目,然後在將與統一你正在檢查的值,它返回true,否則返回false。
prep(N, List) :-
nth0(I1, List, N),
nth0(I2, List, N),
not(I1 =:= I2).
第三次嘗試:這工作,並儘快第一個重複已經發現
prep(M, List) :-
nth0(I1, List, N),
nth0(I2, List, N),
not(I1 =:= I2), !,
M == N.
代表(N,list)返回: - 追加(L1,[N | _] ,列表),追加(_,[N | _],L1),\ +(REP(_,L1))。
下面是使用dif/2
實現聲音不平等的純粹版本。 dif/2
由B-Prolog,YAP-Prolog,SICStus-Prolog和SWI-Prolog提供。
firstdup(E, [E|L]) :- member(E, L). firstdup(E, [N|L]) :- non_member(N, L), firstdup(E, L). member(E, [E|_L]). member(E, [_X|L]) :- member(E, L). non_member(_E, []). non_member(E, [F|Fs]) :- dif(E, F), non_member(E, Fs).
的優點是,它也可以用更一般的查詢中使用:
?- firstdup(E, [A,B,C]). E = A, A = B ; E = A, A = C ; E = C, B = C, dif(A, C) ; false.
在這裏,我們得到了三個答案:A
是前兩個答案的重複,但在兩個不同的理由:A
可能等於B
或C
。在第三個答案中,B
是重複的,但只有在C
與A
不同時纔會重複。
理解定義,讀:-
作爲箭頭←那麼,什麼是對右手邊是你知道什麼,左邊是你的結論是什麼。畢竟,你可能會試圖遵循「執行的線索」,因此往往在開始時往往往那個方向閱讀謂詞。但通常這個線程會導致無法理解。
的第一條規則如下:
提供E
是我們的結論是[E|L]
具有E
作爲第一個重複列表L
的元素。
第二條規則如下:
提供E
是L
第一個重複(這裏不慌,說我們不知道...),並提供了N
不是我們得出這樣的結論L
元素[N|L]
有E
作爲第一個重複。
在許多Prolog系統中提供了member/2
謂詞,nonmember(X,L)
可以定義爲maplist(dif(X),L)
。因此,人們將定義firstdup/2
而爲:
firstdup(E, [E|L]) :- member(E, L). firstdup(E, [N|L]) :- maplist(dif(N), L), firstdup(E, L).
如果文本的最後一行讀取「...和非成員(X,L)」可以定義爲'maplist(dif(X),L)'......「,則可能更好。到'X'和'L'在那裏。 :) – 2012-04-29 07:14:25
@Will Ness:完成,謝謝! – false 2012-04-29 19:36:58
在這個答案,我們提高this earlier answer給出的邏輯純代碼。一步一步:
我們結合兩個謂詞memberd/2
和non_member/2
一個,memberd_t/3
,其使用reifying列表成員成真值(true
或false
)的附加參數。
memberd_t/3
相當於memberd/2
+ non_member/2
,所以我們可以定義它是這樣的:
memberd_t(X,Xs,true) :- memberd(X,Xs). memberd_t(X,Xs,false) :- non_member(X,Xs).
,或者相反,我們可以定義memberd/2
和non_member/2
像這樣:
memberd(X,Xs) :- memberd_t(X,Xs,true). non_member(X,Xs) :- memberd_t(X,Xs,false).
實際上,我們使用了一個調整實現memberd_t/3
-one w更好的決定論。
讓我們看到memberd_t/3
其實涵蓋memberd/2
和non_member/2
!
?- memberd_t(X,[1,2,3],T). T = true , X=1 ; T = true , X=2 ; T = true , X=3 ; T = false, dif(X,1), dif(X,2), dif(X,3).
採取以下變種謂詞firstdup/2
(defined earlier)的作爲我們的出發點:
firstdup(E,[X|Xs]) :- ( memberd(X,Xs), E=X ; non_member(X,Xs), firstdup(E,Xs) ).
讓我們來替換使用的memberd/2
和non_member/2
與memberd_t/3
!
firstdup(E,[X|Xs]) :- ( memberd_t(X,Xs,true), E=X ; memberd_t(X,Xs,false), firstdup(E,Xs) ).
讓我們葫蘆memberd_t/3
!
firstdup(E,[X|Xs]) :- memberd_t(X,Xs,T), ( T=true -> E=X ; T=false, firstdup(E,Xs) ).
上面的圖案pred_t(OtherArgs,T), (T = true -> Then ; T = false, Else)
可以更簡明使用if_/3
,書寫if_(pred_t(OtherArgs),Then,Else)
表示。
firstdup(E,[X|Xs]) :- if_(memberd_t(X,Xs), E=X, firstdup(E,Xs)).
讓我們運行一些查詢!
?- firstdup(1,[1,2,3,1]). true. % succeeds deterministically ?- firstdup(X,[1,2,3,1]). X = 1. % succeeds deterministically ?- firstdup(X,[A,B,C]). % succeeds, leaving behind a choicepoint A=X , B=X % ... to preserve the full solution set. ; A=X , dif(B,X), C=X ; dif(A,X), B=X , C=X ; false.
我還是一個Prolog begginer,這對我來說有點難理解。我們沒有在課堂上講授Prolog,而且我幾乎沒有時間自己體面地學習它,這個練習只給予了自學,所以我稍後會試着更好地理解它。感謝您的時間! :) – Zezinho 2012-04-21 16:57:12
不客氣..這是一種奇怪的語言,毫無疑問。它爲你做了很多事情,而不是你必須告訴它隨時都在做什麼,所以你需要了解它能在背後做些什麼才能提出最新的解決方案。 – magus 2012-04-21 17:09:53
與你最後的加法,'prep(5,[1,3,5,3,5])''返回'true'。 (N,[1,3,5,3,5])。 N = 3; N = 5; N = 3; N = 5; No'。 – 2012-04-23 08:46:40