use strict; use warnings; sub r(&$@) { my $cb = shift(@_); my %seen; local *_r = sub { my @v = @_; return if $seen{join $;, @v}++; return if not $cb->(@v); return if @v == 1; for (0..$#v) { my @v_ = @v; splice(@v_, $#v-$_, 1); _r(@v_); } }; _r(sort @$_) foreach @_; } r { print(@_, "\n"); 1 } [ qw( A B C D ) ], [ qw( A B C E ) ], [ qw( A B C F G ) ];
Output:
ABCD ABC AB A B AC C BC ABD AD D BD ACD CD BCD ABCE ABE AE E BE ACE CE BCE ABCFG ABCF ABF AF F BF ACF CF BCF ABCG ABG AG G BG ACG CG BCG ABFG AFG FG BFG ACFG CFG BCFG
Both the implementation and the algorithm can surely be improved.
Update: The code block now returns a value. This allows the option to skip, as desired.
Update: Slightly modified to attain your ultimate goal.
Update: (Bug fix) Added sort.
Update: I can't think of another algorithm. This will likely be my last solution.
In reply to Re: Powerset short-circuit optimization
by ikegami
in thread Powerset short-circuit optimization
by Limbic~Region
For: | Use: | ||
& | & | ||
< | < | ||
> | > | ||
[ | [ | ||
] | ] |