Beefy Boxes and Bandwidth Generously Provided by pair Networks
There's more than one way to do things
 
PerlMonks  

Re^3: Cartesian Cross-Products

by Anonymous Monk
on Apr 15, 2009 at 19:09 UTC ( [id://757778]=note: print w/replies, xml ) Need Help??


in reply to Re^2: Cartesian Cross-Products
in thread Cartesian Cross-Products

"The Perl Way"
sub cartesian { my @C = map { [ $_ ] } @{ shift @_ }; foreach (@_) { my @A = @$_; @C = map { my $n = $_; map { [ $n, @$_ ] } @C } @A; } return @C; }

Replies are listed 'Best First'.
Re^4: Cartesian Cross-Products
by saenns (Initiate) on Aug 09, 2010 at 17:33 UTC
    Hi, Perl n00b here. Check out my recursive solution for any number of sets. Feel the scheme.
    sub cartesian { my @sets = @_; # base case if (@sets == 0) { return ([]); } my @first = @{@sets[0]}; # recursive call shift @sets; my @rest = cartesian(@sets); my @result = (); foreach my $element (@first) { foreach my $product (@rest) { my @newSet = @{$product}; unshift (@newSet, $element); push (@result, \@newSet); } } return @result; }

      Update: Sorry, deleted rerroneous post

      Rule One: "Do not act incautiously when confronting a little bald wrinkly smiling man."

      I had the same thought also (to use a recursive algorithm), but your code didn't seem complete or it didn't work the way I expected. There are certainly more Perlish ways to code this with map etc., but it works. Cartesian product of multiple lists using recursion.

      use Data::Dumper; my $letters = [qw(a b c)]; my $numbers = [1..3]; my $words = [qw(you me)]; my $result = cartesian($letters, $numbers, $words); print Dumper( $result ); sub cartesian { my ($set, @sets) = @_; my @expanded; # base case if ( !@sets ) { foreach ( @{$set} ){ push @expanded, [$_]; } } # recursive call else { my @product = @{ cartesian(@sets) }; foreach my $element ( @{$set} ) { foreach my $product ( @product ) { push @expanded, [ $element, @{$product} ]; } } } return \@expanded; }
Re^4: Cartesian Cross-Products
by Anonymous Monk on Jan 20, 2010 at 23:23 UTC
    That
    my @C = map { [ $_ ] } @{ shift @_ };
    Can be simplified to:
    my @C = [];
    Don't believe me? Try it. Also, it now works correctly in the case you pass no arguments to the function. This may be a matter of taste, but I prefer the leftmost array to be the outermost loop. So that leaves us with:
    sub cartesian { my @C = []; foreach (reverse @_) { my @A = @$_; @C = map { my $n = $_; map { [ $n, @$_ ] } @C } @A; } return @C; }

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: note [id://757778]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others scrutinizing the Monastery: (5)
As of 2025-04-22 12:12 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found

    Notices?
    erzuuliAnonymous Monks are no longer allowed to use Super Search, due to an excessive use of this resource by robots.