在prolog中重新排序列表

时间:2014-10-09 11:20:13

标签: prolog

我想根据从小到大的子列表长度的出现重新排列列表。例如,预期的答案由子列表的长度数重新排列,有一个长度为4,两个长度1,三长3和长4。

示例查询及其结果:

lists_ascending([[a,b],[c],[a,b,c],[d,d,d],[d,s],[s],[d,s,s,a], [s,a],[s,t],[a,b,w]],Ls).
Ls = [[d,s,s,a],[c],[s],[a,b,c],[d,d,d],[a,b,w],[a,b],[d,s],[s,a],[s,t]]

我的想法是首先计算每个长度,然后重新排列。到目前为止,我所做的是使用模式[length-number]收集长度等于第一个子列表的子列表的数量。

count([],[0-0]).
count([A|B],[L-N]):-
    length(A,L),
    same_length(B,L,M),
    N is M+1.

same_length([],_,0).
same_length([A|B],L,N) :-
    (   length(A,L)->
        same_length(B,L,M),
        N=M+1
    ;   same_length(B,L,N)
    ).  

计数(LIST,X)输出如下:

21 ?- count_slot([[2],[3],[4],[2,3,4]],X).
X = [1-3]. 

但预期的输出是[1-3,3-1],我不知道如何处理其余子列表(逐个删除?)并根据模式重新排列它们[1-3, 3-1]。

有人可以帮忙吗?谢谢你提前。

1 个答案:

答案 0 :(得分:1)

您需要考虑可能存在与第一个子列表长度相同的多个子列表的情况。显然,你的count/2只描述了最多只有一个的情况,因为它的第二个参数是一个长度为1的列表。

要收集与第一个子列表长度相同的子列表,请考虑例如:

lists_same_length_as_first([Ls|Lss], Subs) :-
    length(Ls, L),
    phrase(length_sublists(L,Lss), Subs).

length_sublists(_, []) --> [].
length_sublists(L, [Sub|Subs]) -->
    (   { length(Sub, L) } -> [Sub]
    ;   []
    ),
    length_sublists(L, Subs).

您还可以使用include/3

更紧凑地编写
lists_same_length_as_first([Ls|Lss], Subs) :-
    length(Ls, L),
    include(length_equal(L), Lss, Subs).

length_equal(L, Ls) :- length(Ls, L).

示例查询及其结果:

?- lists_same_length_as_first([[2],[3],[4],[2,3,4]], Ls).
Ls = [[3], [4]].

顺便说一句,我给出了这个问题的完整解决方案here