2017-01-17 68 views
2

我想寫一個謂詞convert/2。 它應該像這樣工作如何在prolog中編寫predicate convert/2?

? - convert([a,[a,a],[a,b],[b,a],[[a,b]],[d],c],X). 
X = [a,c,[a],[d],[a,b],[[a,b]]] 
yes 

? - convert([[a,[a,b]],[a,[c,b]],[[a,b],a]], X). 
X = [[a,[a,b]],[a,[b,c]]] 
yes 

? - convert([[a,b],[a,[a]],[a,b,c]],X). 
X = [[a,b],[a,[a]],[a,b,c]] 
yes 

我知道,我必須先找到列表的長度。 然後我必須排序它,最後我必須合併重複的元素。

+0

這個例子很好;定義算法的嘗試也很好;它仍然有助於明確定義'convert/2'實際上在做什麼。 –

+0

我想寫一個謂詞轉換/ 2,它將任何列表(可能有 重複元素)減少到一個列表,其中每個不同的元素只出現一次 並使用特定的順序。 –

+0

我很難理解一個細節:爲什麼'[a,b]'在'[[a,b]]之前''。查詢'convert([[a,[b,c]],[a,b,c]],X)'的結果是什麼? –

回答

2

所以,不知道您的排序算法是什麼,我創建了一個有些通用的例子來說明這個概念:

convert(X, X) :- \+is_list(X). 
convert([],[]). 
convert([InHead|InTail], OutList) :- 
    convert(InHead, OutHead), 
    convert(InTail, OutTail), 
    append([OutHead], OutTail, UnsortedList), 
    sort(UnsortedList, DeduplicatedList), 
    custom_sort(DeduplicatedList, OutList). 

custom_sort(List,Sorted) :- 
    permutation(List,Sorted), 
    is_sorted(Sorted). 

is_sorted([]). 
is_sorted([_]). 
is_sorted([X,Y|T]) :- 
    % perform any number of tests on X and Y here 
    % default is: 
    X @=< Y, 
    is_sorted([Y|T]). 

這遞歸轉換列表中的每個列表,然後使用內置的排序刪除重複項,然後應用自定義排序(建立在幼稚排序上)。

我最初認爲我已經破解了你的排序算法(按列表的深度排序(其中一個原子的深度爲0),然後按列表的長度(其中一個原子的長度爲0),然後通過列表),提出了以下幾點:

list_length(X, 0) :- 
    \+is_list(X). 
list_length(X, Y) :- 
    is_list(X), length(X, Y). 

list_depth(X, 0) :- \+is_list(X). 
list_depth([], 0). 
list_depth([Head|Tail], Y) :- 
    list_depth(Head, YH), 
    list_depth(Tail, YTP), 
    YT is YTP - 1, 
    Y is max(YH, YT) + 1. 

is_sorted([X,Y|T]) :- 
    list_length(X, XL), 
    list_length(Y, YL), 
    list_depth(X, XD), 
    list_depth(Y, YD), 
    (XD < YD ; 
     (XD = YD, 
     (XL < YL ; 
      (XL = YL, 
      X @=< Y) 
     ) 
    ) 
    ), 
    is_sorted([Y|T]). 

...但失敗了你的第三個例子,其中,[A,[A],[A,b,C]具有深度2,然後深度1 ,所以我將上面的代碼展示給你,讓你的享受更勝一籌。

編輯: 從鮑里斯的評論,就足以讓我認識到,通過扁平長度排序,然後深入適用於所有的例子,它看起來像這樣:

list_length(X, 0) :- 
    \+is_list(X). 
list_length(X, Y) :- 
    is_list(X), 
    flatten(X, Z), 
    length(Z, Y). 

list_depth(X, 0) :- \+is_list(X). 
list_depth([], 0). 
list_depth([Head|Tail], Y) :- 
    list_depth(Head, YH), 
    list_depth(Tail, YTP), 
    YT is YTP - 1, 
    Y is max(YH, YT) + 1. 

is_sorted([X,Y|T]) :- 
    list_length(X, XL), 
    list_length(Y, YL), 
    list_depth(X, XD), 
    list_depth(Y, YD), 
    (XL < YL ; 
     (XL = YL, 
     (XD < YD ; 
      (XD = YD, 
      X @=< Y) 
     ) 
    ) 
    ), 
    is_sorted([Y|T]). 
0

好吧,不過你可以替換其他內置函數「排序」?這裏最重要的是

+0

好的,我解決了它。我用:insert(X,[],[X])。插入(X,[Y | Tail],[Y | L1]): - Y @ = rafaluf

+0

你的回答是一個問題,你的解決方案是一個評論?這是倒退,編輯您的答案以刪除問題並將您的答案從評論中輸入答案! –