Beefy Boxes and Bandwidth Generously Provided by pair Networks
We don't bite newbies here... much
 
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 romping around the Monastery: (3)
As of 2024-04-24 02:49 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found