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 ) ]; #### 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