2017-01-17 35 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

你的回答是一个问题,你的解决方案是一个评论?这是倒退,编辑您的答案以删除问题并将您的答案从评论中输入答案! –