chettyharish
chettyharish

Reputation: 1734

Glob for generating all permutations

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

Answers (1)

ThisSuitIsBlackNot
ThisSuitIsBlackNot

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;
}

Output:

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

Related Questions