我正在寻找这样的谓词:
?- subset([1,2,3], X).
X = [] ;
X = [1] ;
X = [2] ;
X = [3] ;
X = [1, 2] ;
X = [1, 2, 3] ;
X = [2, 3] ;
...
我见过一些subset
实现,但是当您想要检查一个列表是否是另一个列表的子集时,它们都可以工作,而不是当您想要生成子集时。有任何想法吗?
这是一个实现:
subset([], []).
subset([E|Tail], [E|NTail]):-
subset(Tail, NTail).
subset([_|Tail], NTail):-
subset(Tail, NTail).
它将生成所有子集,尽管不是按照示例中显示的顺序。
根据评论者的要求,这里有一个解释:
第一个子句是基本情况。它声明空列表是空列表的子集。
第二和第三条处理递归。第二个子句指出,如果两个列表具有相同的 Head 并且右列表的尾部是左列表尾部的子集,则右列表是左列表的子集。
第三个子句指出,如果我们跳过左列表的头部,而右列表是左列表尾部的子集,那么右列表是左列表的子集。
上面显示的过程生成有序集。对于无序集,您可以使用permutation/3
:
unordered_subset(Set, SubSet):-
length(Set, LSet),
between(0,LSet, LSubSet),
length(NSubSet, LSubSet),
permutation(SubSet, NSubSet),
subset(Set, NSubSet).
在http://www.probp.com/publib/listut.html上,您会找到一个谓词的实现,它可以满足subseq0
您的要求:
subseq0(List, List).
subseq0(List, Rest) :-
subseq1(List, Rest).
subseq1([_|Tail], Rest) :-
subseq0(Tail, Rest).
subseq1([Head|Tail], [Head|Rest]) :-
subseq1(Tail, Rest).
一个简短的解释:subseq0(X, Y)
检查 Y 是否是 X 的子集子序列,同时subseq1(X, Y)
检查 Y 是否是 X 的适当 子集子序列。
由于集合的默认表示是具有唯一元素的列表,因此您可以使用它来获取所有子集,如下例所示:
?- subseq0([1,2,3], X).
X = [1, 2, 3] ;
X = [2, 3] ;
X = [3] ;
X = [] ;
X = [2] ;
X = [1, 3] ;
X = [1] ;
X = [1, 2] ;
false.
我们还可以通过从超集中删除子集的项目来进行测试。
% to delete : an item can be deleted it its in the head or in the tail of a list
delete(I,[I|L],L).
delete(I,[H|L],[H|NL]) :- delete(I,L,NL).
% an [] is an item of an set.A set is a subset of we can recursively delete its head item from the super set.
subset(_,[]).
subset(S,[I|SS]) :- delete(I,S,S1), subset(S1,SS).
例子:
subset([a,b,c],S).
S = []
S = [a]
S = [a, b]
S = [a, b, c]
S = [a, c]
S = [a, c, b]
S = [b]
S = [b, a]
S = [b, a, c]
S = [b, c]
S = [b, c, a]
S = [c]
S = [c, a]
S = [c, a, b]
S = [c, b]
S = [c, b, a]
subset([a,b,a,d,e],[a,e]).
1true
根据定义,集合是不同对象的集合。子集过程不应该关心集合中元素的顺序(在参数中)。适当的解决方案(swi prolog)可能如下所示:
subset(_, []).
subset([X|L], [A|NTail]):-
member(A,[X|L]),
subset(L, NTail),
not(member(A, NTail)).
对于问题 ?- subset([1,2,3], E) 它将生成:
E = [] ;
E = [1] ;
E = [1, 2] ;
E = [1, 2, 3] ;
E = [1, 3] ;
E = [2] ;
E = [2, 3] ;
E = [3] ;
E = [3, 2] ;
false.
希望它会有所帮助!
append([],L,L).
append([H|T],L,[H|L1]):-append(T,L,L1).
subset([X|T],[X|L]) :-subset(T,L).
subset([X|T],[G|L]) :-subset([X],L),append(L2,[X|L3],[G|L]),append(L2,L3,L4),subset(T,L4).
subset([],_).
----------------------------------------------
?- subset([1,2],[1,2]).
yes
?- subset([1,2],[2,1]).
yes
?- subset([1,1],[1,2]).
no
?- subset(D,[1,2]).
D = [1,2] ;
D = [1] ;
D = [2,1] ;
D = [2] ;
D = '[]' ;
no