2014-01-17 63 views
1

我給出了2個列表,例如K=[a,b,c,d,e,f,g]L=[a,b,1,d,e,2,g]。當這兩個列表有兩個不同的元素,那麼他們很友善。友好列表序言

這是我已經試過:

friendly(K,L):- 
    append(L1,[Z],A1), 
    append(A1,L2,A2), 
    append(A2,[Q],A3), 
    append(A3,L3,K), 
    append(L1,[Y],B1), 
    append(B1,L2,B2), 
    append(B2,[W],B3), 
    append(B3,L3,L), 
    Z\=Y, 
    Q\=W. 

謝謝大家這麼多,最後我找到了正確的代碼:

friend(L1,L2):- 
append(A,Y,L1), 
append([Z|T],[F|TT],Y), 
append(A,Q,L2), 
append([R|T],[O|TT],Q), 
Z\=R, 
F\=O. 
+0

請您澄清,*當這兩個列表有2個不同的元素*?你的意思是他們只在兩個元素上有所不同,其餘部分必須是相同的?我認爲秩序並不重要? '[1,2,3]'和'[a,b,c]'友好嗎?那麼'[a,b,c,d]'和'[a,b]'呢? – lurker

+0

你的意思是他們只在兩個元素上有所不同,其餘必須是相同的?是的,命令很重要。是[1,2,3]還是[a,b,c]友好?不。[a,b,c,d]和[a,b]怎麼樣?是的,他們友好 – John

+0

這個友好列表(K,L)怎麼樣: - append(L1,[C | L2],T1), append(T1,[F | L3],K), append(L1, D | L2],Y1), 附加(Y1,[E | L3],L), C \ = D, F \ = E。 – John

回答

1

您可以使用append/3以這種方式找到第一個不同的元素。

first_different(L1,L2, R1,R2) :- 
    append(H, [E1|R1], L1), 
    append(H, [E2|R2], L2), 
    E1 \= E2. 

H是公共部分,R1,R2是'餘數'。此代碼更符合上述第二條評論。

現在你必須應用兩次這個助手謂詞,第二次也是'剩餘'必須是相等的,或者其中一個必須是空的。那是

friendly(L1,L2) :- 
    first_different(L1,L2,R1,R2), 
    first_different(R1,R2,T1,T2), 
    once((T1=T2;T1=[];T2=[])). 

另外,使用一些內建可能是有益的。這應該工作

friendly(L1,L2) :- findall(_,(nth1(I,L1,E1),nth1(I,L2,E2),E1\=E2),[_,_]). 
1

那豈不是更好地做這樣的事情下列?

diff([], [], []). 
diff([], K, K). 
diff(L, [], L). 
diff([H | TL], [H | TK], D) :- diff(TL, TK, D),!. 
diff([HL | TL], [HK | TK], [HL, HK | D]) :- diff(TL, TK, D),!. 

friendly(K, L) :- diff(K, L, D), length(D, Length), Length < 3. 

但你的問題實在是尚未。例如我的程序真的關心訂單,所以[a,x,b][a,b]對我的定義不友好。

+0

這兩個削減不會幫助很多。相反,'friendly/2'中的'once/1'完全相同。但是我寧願用一個明確的不平等測試,比如'dif(HL,HK)'。 – false

+0

感謝您的提示!很久以前,我纔剛開始關於Prolog的記憶。還有很長的路要走:) –

1

我還是有點不確定的「友好」列表中的總定義,但我認爲這可能會回答它:

friendly(A, B) :- 
    friendly(A, B, 2). 
friendly([H|TA], [H|TB], C) :- 
    C > 0, 
    friendly(TA, TB, C). 
friendly([HA|TA], [HB|TB], C) :- 
    HA \= HB, 
    C > 0, 
    C1 is C-1, 
    friendly(TA, TB, C1). 
friendly(A, [], C) :- 
    length(A, L), 
    L =< C. 
friendly([], B, C) :- 
    length(B, L), 
    L =< C. 
friendly(A, A, 0). 

我假設的定義友好的意思是列表在兩個差異的最大值之外的「鎖定步驟」中。

1

命令是否重要?是否列表(每個元素是唯一的)還是(允許重複)?

假設

  • 順序無關緊要([1,2,3]和[1,3,2])被視爲是相同的),和
  • 重複並不重要( [1,2,3,1]和[1,2,3])被視爲相同

像這樣的東西可能是沿着線你要找的東西:

friendly(Xs,Ys) :- 
    set_of(
    E , 
    (
     (  member(E,Xs) , 
     not(member(E,Ys)) 
    ) 
    ; 
     (
      member(E,Ys) , 
     not(member(E,Xs)) 
    ) , 
    Zs 
    ) , 
    length(Zs , L) , 
    L =< 2 
    . 

找到每個列表的所有元素的集合,如果得到的列表的長度爲0,1或2,則不成功。

1

我想出了一些與其他類似的東西..我只是保留'_'項目列表(diff_list的最後一個參數) - 每個差異一個,是同一個索引處的值差異,或者長度差異,然後最後以friendly/2檢查是否有2個項目。

% recursion base 
diff_list([], [], []). 

% the head of both lists are the same, don't add to diff list 
diff_list([HK|TK], [HK|TL], Diff) :- 
    diff_list(TK, TL, Diff). 

% the above rule failed, so must be a difference, add a '_' 
diff_list([_|TK], [_|TL], [_|Diff]) :- 
    diff_list(TK, TL, Diff). 

% 1st list is empty, but the 2nd isn't. That's a diff again. 
diff_list([], [_|TL], [_|Diff]) :- 
    diff_list([], TL, Diff). 

% 2nd list is empty, but the 1st isn't. Another diff. 
diff_list([_|TK], [], [_|Diff]) :- 
    diff_list(TK, [], Diff). 

% friendly is true if the diff list length unifies with 2 item length list [_,_] 
friendly(K, L) :- 
    diff_list(K, L, [_,_]).