解决这个问题的方法相当简单:显然,空集合中只有一种组合:空集合。
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].
编辑
假设您想排除空列表,您可以通过在调用时添加另一个检查来简单地实现:
?- 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).
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.
[a,b,a]
吗? - Willem Van Onsem[a,a,a]
不被枚举。 - Willem Van Onsem