note
jaredor
<p>
Late to the party and, not only that, but wearing the same outfit as some (see [id://975394|ambrus]'s link above). I think the best answer for you is [id://975266|toolic]'s. My answer that follows just fills in a few conceptual details for you about the [wp://Power Set], illustrated by two functions that do the job two different ways.
</p>
<readmore>
<p>
Earlier, I had copied this problem to my notepad and had misremembered your question as being about a string, "ABCD", rather than an array of elements. So both functions take in a string and return a list of strings. This makes my answer slightly different from the others in the recursive case and bulky in the enumeration case.
</p>
<h3>Power Set</h3>
<p>
Given a set, A, the set of all subsets of elements of A is called the power set of A, here denoted P(A). A power set, P(A), of finite set A has size 2<sup>N</sup>. So your example should have 16 results. (Note, one of those subsets is the empty set / empty string). Finding all combinations of elements of a set is an equivalent notion.
</p>
<p>Power sets get very big, very fast, so in general you don't see many applications for power sets unless you are writing advertisements for how many ways customers can put condiments on their hamburgers. If this question is motivated by a real-world problem (i.e., one that doesn't get a grade) it would be interesting to some of us if you could post some details about it.
</p>
<h3>recursion</h3>
<p>
The first function, rpow, shows the recursive solution and its map block indicates that the results of the recursed function call are doubled, hence you can see how the 2<sup>N</sup> subsets are built up.
</p>
<code>
#!/usr/bin/env perl
use Modern::Perl;
sub rpow {
my ($p, $q) = $_[0] =~ /(.)(.*)/;
return $_[0] ? map { ($p.$_, $_) } rpow ($q) : '';
}
say join ("\n", rpow 'ABCD');
</code>
<h3>enumeration</h3>
<p>
The second function, bpow, is a direct enumeration of the power set by using the on/off nature of a bit in the binary representation of a number as a representation for the in/out selection of an element of A for a given element of P(A). That is, it runs a bit-mask of each non-negative integer less than 2<sup>N</sup> against your string. It produces the same results as rpow (in reverse order).
</p>
<code>
#!/usr/bin/env perl
use Modern::Perl;
sub bpow {
map { my $m = unpack("b*", pack("i*",$_));
$m =~ s/0/\0/g;
$m =~ s/1/~"\0"/ge;
$m & $_[0];
} 0..2**length($_[0])-1
}
say join ("\n", bpow 'ABCD');
</code>
</readmore>
975263
975263