Reputation: 1734
I was using the following code to generate all the possible combinations of a permutation and store it in @apriorirow , This works correctly for small $globstring, but produces null @apriorirow for large inputs. How can I solve this problem?
$globstring = join ',', @distinctelements;
@apriorirow = glob "{$globstring}" x $i;
print "$globstring";
Upvotes: 2
Views: 234
Reputation: 24063
What you are generating with glob
is neither a combination nor a permutation, but a Cartesian product (also known as the cross product). Storing the Cartesian product in an array will use a lot of memory for non-trivial input data. You can use Set::CrossProduct to iterate through the Cartesian product one tuple at a time:
use Set::CrossProduct;
my $rows = 3;
my @elements = qw(a b c);
my @array;
push @array, \@elements for 1..$rows;
my $iterator = Set::CrossProduct->new(\@array);
while (my $tuple = $iterator->get) {
say join ',', @$tuple;
}
a,a,a
a,a,b
a,a,c
a,b,a
a,b,b
a,b,c
a,c,a
a,c,b
a,c,c
b,a,a
b,a,b
b,a,c
b,b,a
b,b,b
b,b,c
b,c,a
b,c,b
b,c,c
c,a,a
c,a,b
c,a,c
c,b,a
c,b,b
c,b,c
c,c,a
c,c,b
c,c,c
Of course, you can also iterate with glob
:
perl -wE 'say while glob "{a,b,c}" x 3'
will do essentially the same thing. But I find the intent clearer with Set::CrossProduct and prefer working with arrays instead of comma-delimited strings (not to mention the additional features Set::CrossProduct has like peeking at the next tuple without actually iterating).
Upvotes: 4