2012-04-21 50 views
5

我需要找到一個列表中的第一個重複的值。序言:一是重複值

prep(3,[1,3,5,3,5]).應該是真實的。

prep(5,[1,3,5,3,5]).應該是假的。

我想檢查與當前值和先前列表成員平等,直到我找到了重複的,如果找到的話,會測試與X平等的,但我不知道該怎麼做的序言!

我感謝任何幫助!由於

回答

0

不知道這是功課/有限制上謂詞你被允許使用,不過這樣會序言做遞歸你。

它說..找到所有重複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. 
+0

我還是一個Prolog begginer,這對我來說有點難理解。我們沒有在課堂上講授Prolog,而且我幾乎沒有時間自己體面地學習它,這個練習只給予了自學,所以我稍後會試着更好地理解它。感謝您的時間! :) – Zezinho 2012-04-21 16:57:12

+0

不客氣..這是一種奇怪的語言,毫無疑問。它爲你做了很多事情,而不是你必須告訴它隨時都在做什麼,所以你需要了解它能在背後做些什麼才能提出最新的解決方案。 – magus 2012-04-21 17:09:53

+0

與你最後的加法,'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

0

代表(N,list)返回: - 追加(L1,[N | _] ,列表),追加(_,[N | _],L1),\ +(REP(_,L1))。

5

下面是使用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可能等於BC。在第三個答案中,B是重複的,但只有在CA不同時纔會重複。

理解定義,讀:-作爲箭頭←那麼,什麼是對右手邊是你知道什麼,左邊是你的結論是什麼。畢竟,你可能會試圖遵循「執行的線索」,因此往往在開始時往往往那個方向閱讀謂詞。但通常這個線程會導致無法理解。

的第一條規則如下:

提供 E是我們的結論是 [E|L]具有 E作爲第一個重複列表 L的元素。

第二條規則如下:

提供 EL第一個重複(這裏不慌,說我們不知道...),並提供了 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). 
+2

如果文本的最後一行讀取「...和非成員(X,L)」可以定義爲'maplist(dif(X),L)'......「,則可能更好。到'X'和'L'在那裏。 :) – 2012-04-29 07:14:25

+1

@Will Ness:完成,謝謝! – false 2012-04-29 19:36:58

3

在這個答案,我們提高this earlier answer給出的邏輯純代碼。一步一步:

  1. 我們結合兩個謂詞memberd/2non_member/2一個,memberd_t/3,其使用reifying列表成員成真值(truefalse)的附加參數。

    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/2non_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/2non_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). 
    
  2. 採取以下變種謂詞firstdup/2defined earlier)的作爲我們的出發點:

     
    firstdup(E,[X|Xs]) :- 
        ( memberd(X,Xs), 
         E=X  
        ; non_member(X,Xs), 
         firstdup(E,Xs) 
        ). 
    
  3. 讓我們來替換使用的memberd/2non_member/2memberd_t/3

     
    firstdup(E,[X|Xs]) :- 
        ( memberd_t(X,Xs,true), 
         E=X 
        ; memberd_t(X,Xs,false), 
         firstdup(E,Xs) 
        ). 
    
  4. 讓我們葫蘆memberd_t/3

     
    firstdup(E,[X|Xs]) :- 
        memberd_t(X,Xs,T), 
        ( T=true 
        -> E=X  
        ; T=false, 
         firstdup(E,Xs) 
        ). 
    
  5. 上面的圖案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.