prolog中列表的所有分区

时间:2015-05-09 17:03:55

标签: prolog

我在Prolog中编码。我想找到列表的所有不同分区。我在这里看一个列表。 每个分区都是一组集合,其中none都是空的,所有集合的并集是主集合,它们的成对交集是空的。

2 个答案:

答案 0 :(得分:4)

首先,我们定义一个辅助谓词list_taken_rest/3

list_taken_rest([], [], []).
list_taken_rest([X|Xs], [X|Ys], Zs) :-
   list_taken_rest(Xs, Ys, Zs).
list_taken_rest([X|Xs], Ys, [X|Zs]) :-
   list_taken_rest(Xs, Ys, Zs).

让我们查看list_taken_rest/3的查询,第一个参数是列表[a,b,c]。作为答案,我们获得了在[a,b,c]Xs之间分离Ys元素的替代方法:

?- list_taken_rest([a,b,c], Xs, Ys).
   Xs = [a,b,c], Ys = []
;  Xs = [a,b],   Ys = [c]
;  Xs = [a,c],   Ys = [b]
;  Xs = [a],     Ys = [b,c]
;  Xs = [b,c],   Ys = [a]
;  Xs = [b],     Ys = [a,c]
;  Xs = [c],     Ys = [a,b]
;  Xs = [],      Ys = [a,b,c].

接下来,我们定义谓词list_partitioned/2,构建于list_taken_rest/3

当我们"走在"列表[X|Xs]

  • 构建单个分区[X|Ys]
  • 该分区包含X作为第一个元素,而部分 Xs中的Ys项。
  • Xs中未加入Ys的所有项目最终都在Zs
  • 我们会一直进行,直到Xs = []成立。
list_partitioned([], []).
list_partitioned([X|Xs], [[X|Ys]|Pss]) :-
   list_taken_rest(Xs, Ys, Zs),
   list_partitioned(Zs, Pss).

完成!我们在某些查询中使用list_partitioned/2

?- list_partitioned([1,2,3,4], Pss).          % query #1
   Pss = [[1,2,3,4]]
;  Pss = [[1,2,3],[4]]
;  Pss = [[1,2,4],[3]]
;  Pss = [[1,2],[3,4]] 
;  Pss = [[1,2],[3],[4]]
;  Pss = [[1,3,4],[2]]
;  Pss = [[1,3],[2,4]]
;  Pss = [[1,3],[2],[4]]
;  Pss = [[1,4],[2,3]]
;  Pss = [[1,4],[2],[3]]
;  Pss = [[1],[2,3,4]]
;  Pss = [[1],[2,3],[4]]
;  Pss = [[1],[2,4],[3]]
;  Pss = [[1],[2],[3,4]]
;  Pss = [[1],[2],[3],[4]].

?- list_partitioned([1,1,1], Pss).            % query #2
   Pss = [[1,1,1]]
;  Pss = [[1,1],[1]] 
;  Pss = [[1,1],[1]]                          %   (redundant answer)
;  Pss = [[1],[1,1]]
;  Pss = [[1],[1],[1]].

请注意,list_partitioned/2根本不关心集合:

  • 如果Ls是一个集合(如查询#1),则所有答案都将是解决方案。
  • 如果Ls包含重复项(如查询#2),我们会得到一些冗余答案。

答案 1 :(得分:1)

part([Single], [[Single]]).

part([First|Others], [[First] | Result]) :-
    part(Others, Result).

part([First|Others], Result) :-
    part(Others, Temp),
    addElement(First, Temp, Result).

/ *       addElement(E,L,R)         当且仅当            R是与L相同的列表列表,除了            其中一个子列表前面有一个额外的E * /

addElement(Element, [FirstList | OtherLists], 
           [ [Element|FirstList] | OtherLists]).
addElement(Element, [FirstList | OtherLists], 
           [ FirstList | Temp] )
              :- addElement(Element, OtherLists, Temp).

执行:

?- part([a,b,c,d],X).
X = [[a], [b], [c], [d]] ;
X = [[a], [b], [c, d]] ;
X = [[a], [b, c], [d]] ;
X = [[a], [c], [b, d]] ;
X = [[a], [b, c, d]] ;
X = [[a, b], [c], [d]] ;
X = [[b], [a, c], [d]] ;
X = [[b], [c], [a, d]] ;
X = [[a, b], [c, d]] ;
X = [[b], [a, c, d]] ;
X = [[a, b, c], [d]] ;
X = [[b, c], [a, d]] ;
X = [[a, c], [b, d]] ;
X = [[c], [a, b, d]] ;
X = [[a, b, c, d]] ;
false.