这个问题的解决方案相当简单:显然空集中只有一种组合:空集:
combs([],[]).
此外,对于每个元素,您可以决定是否添加它:
combs([H|T],[H|T2]) :-
combs(T,T2).
combs([_|T],T2) :-
combs(T,T2).
由于您按照列表的顺序选择(或删除),这可以保证您以后不会重新决定选择a
。如果你喂它[a,b,c]
,它永远不会生成类似的东西[b,a,c]
,因为一旦决定挑选/放下a
,它不能添加b
并重新决定a
.
运行这个给出:
?- combs([a,b,c],L).
L = [a, b, c] ;
L = [a, b] ;
L = [a, c] ;
L = [a] ;
L = [b, c] ;
L = [b] ;
L = [c] ;
L = [].
如果您想以相反的方式生成它(进行更多测试以首先删除元素,而不是添加它们,您可以简单地交换递归语句):
combs([],[]).
combs([_|T],T2) :-
combs(T,T2).
combs([H|T],[H|T2]) :-
combs(T,T2).
在这种情况下,结果将是:
?- combs([a,b,c],L).
L = [] ;
L = [c] ;
L = [b] ;
L = [b, c] ;
L = [a] ;
L = [a, c] ;
L = [a, b] ;
L = [a, b, c].
EDIT
如果您想排除空列表,您可以通过在调用中添加另一个检查来简单地完成此操作:
?- combs([a,b,c],L),L \= [].
您可以在函数中定义它,例如:
combs_without_empty1(LA,LB) :-
combs_without_empty1(LA,LB),
LB \= [].
或者通过重写comb/2
功能。在这种情况下,你最好使用累加器计算当前选定元素的数量:
combs_without_empty(L,C) :-
combs_without_empty(L,0,C).
The combs_without_empty/3
有点复杂。如果列表仅包含一个元素,则应检查是否N
大于零。如果是这种情况,我们可以选择是否添加该元素。如果N
为零,我们必须将其包括在内。所以:
combs_without_empty([A],_,[A]).
combs_without_empty([_],N,[]) :-
N > 0.
我们还必须实现一个递归部分,该部分将递增N
假设我们选择一个元素:
combs_without_empty([_|T],N,T2) :-
combs_without_empty(T,N,T2).
combs_without_empty([H|T],N,[H|T2]) :-
N1 is N+1,
combs_without_empty(T,N1,T2).
把它们放在一起给出:
combs_without_empty(L,C) :-
combs_without_empty(L,0,C).
combs_without_empty([A],_,[A]).
combs_without_empty([_],N,[]) :-
N > 0.
combs_without_empty([_|T],N,T2) :-
combs_without_empty(T,N,T2).
combs_without_empty([H|T],N,[H|T2]) :-
N1 is N+1,
combs_without_empty(T,N1,T2).
其产生:
?- combs_without_empty([a,b,c],L).
L = [c] ;
L = [b, c] ;
L = [b] ;
L = [a, c] ;
L = [a] ;
L = [a, b, c] ;
L = [a, b] ;
false.