生成仅包含特定大小的子集的集合的powerset

时间:2011-11-14 18:36:26

标签: erlang set subset powerset

我想生成一组P(S)的powerset S。我希望P(S)只有一个等于一定大小的子集。

例如,如果我们有S = [1,2,3,4],则limited_powerset(S,3)将为[[1,2,3],[2,3,4],[1,3,4],[1,2,4]].

Hynek Pichi Vychodil提供了Erlang中一般powerset生成的一个很好的例子(谢谢!):

generate([]) -> [[]];
generate([H|T]) -> PT = generate(T),
  generate(H, PT, PT).

generate(_, [], Acc) -> Acc;
generate(X, [H|T], Acc) -> generate(X, T, [[X|H]|Acc]).

如何修改它以仅包含特定大小的子集?引入Limit变量并将最后一行更改为

case length([X|H]) < Limit of
        true -> 
            ps(X, T, Acc, Limit);
        false -> 
            ps(X, T, [[X|H]|Acc],Limit)
    end.

无济于事。

P.S。我想子集的数量将小于N!,但我怎样才能准确计算它呢?

1 个答案:

答案 0 :(得分:3)

这将做你想要的:

limited_powerset(L, N) ->
  {_, Acc} = generate(L, N),
  Acc.

generate([], _) ->
  {[[]], []};
generate([H|T], N) ->        
  {PT, Acc} = generate(T, N),
generate(H, PT, PT, Acc, N).

generate(_, [], PT, Acc, _) -> 
  {PT, Acc};
generate(X, [H|T], PT, Acc, N) when length(H)=/=N-1 ->
  generate(X, T, [[X|H]|PT], Acc, N);
generate(X, [H|T], PT, Acc, N) ->    
  generate(X, T, [[X|H]|PT], [[X|H]|Acc], N).

这不是微不足道的。它让我难过了一会儿。诀窍是你需要在整个算法中维护完整的powerset累加器,并为有限集创建第二个累加器。