in reply to cross combinations

In Perl5, it only takes four lines:
sub cross { my $f = shift or return; # Nothing. @_ or return map {[$_]} @{$f}; # Handle one argument. my @r = cross(@_); # Recurse. map {my $l = $_; map {[$l, @$_]} @r} @$f; # Distribute. }
However, I think that the cross product of nothing should be the empty set ([]), which would make the function even simpler as it loses a special case:
sub cross { my $f = shift or return []; # Nothing. my @r = cross(@_); # Recurse. map {my $l = $_; map {[$l, @$_]} @r} @$f; # Distribute. }
Perl --((8:>*

Replies are listed 'Best First'.
Re^2: cross combinations
by eric256 (Parson) on Oct 28, 2005 at 14:23 UTC

    You can code the exact same thing in the same number of lines in p6. That was not the real point though. I don't think anyone was golfing. The p6 solution above has something yours doesn't, take and gather. By default (at least last week ;) ) take and gather are lazy.

    sub cross (*$f, *@a) { return unless $f; @a or return @{$f}.map:{[$_]} ; # Handle one argument. my @r = cross(@a); # Recurse. @$f.map:{my $l = $_ ; @r.map:{[$l, @$_]} }; # Distribute. } cross().perl.say; cross([],[1]).perl.say; cross([1,2]).perl.say; cross([1,2],[3]).perl.say; cross([1],[2],[3]).perl.say; cross([1],[2],[3,4]).perl.say;

    ___________
    Eric Hodges $_='y==QAe=e?y==QG@>@?iy==QVq?f?=a@iG?=QQ=Q?9'; s/(.)/ord($1)-50/eigs;tr/6123457/- \/|\\\_\n/;print;
      The p6 solution above has something yours doesn't, take and gather. By default (at least last week ;) ) take and gather are lazy.
      Sure, take and gather are lazy. But since you need the entire list anyway, it doesn't really matter, does it? Lazy lists are nice if you don't need the entire thing - if you need the entire thing, it hardly matters.

      I still don't see the point of the various Perl6 solutions. The solution you present above doesn't have any benefits of the Perl5 solution - it just uses a different syntax, not even syntax that's significantly shorter, or easier to understand (it isn't harder or longer either - just different). It doesn't score on the "see how much easier this problem is in perl6" scale.

      Perl --((8:>*

        Who said anything about this being the easier solution? My post was just to show you that it could be done the same in pugs. You didn't present any point except that yours was shorter so i was pointing out that isn't true. BTW lazy has a different advantage. If its lazy you get it as you need it, so you don't spend time processing until you get to stuff you need. So even if you need it all this can spread the processing time out instead of one giant load period in the begining. when all you are doing is printing out the matches that doesn't help much, but if you were doing something else it could be very helpful.


        ___________
        Eric Hodges $_='y==QAe=e?y==QG@>@?iy==QVq?f?=a@iG?=QQ=Q?9'; s/(.)/ord($1)-50/eigs;tr/6123457/- \/|\\\_\n/;print;
        Lazy lists are nice if you don't need the entire thing - if you need the entire thing, it hardly matters.

        I heartily disagree. If the list is large and you don't need the entire thing at once, then being lazy saves you a lot of memory, and can be the difference between getting an answer a minute later, and having your program crash. (For instance that's why you want to use while to loop through a large file rather than for.)

        Combining lists quickly creates a combinatorial explosion where you really don't want it all in memory if you don't need it there.

Re^2: cross combinations
by xdg (Monsignor) on Oct 28, 2005 at 11:42 UTC

    Cool solution -- but the original isn't recursive, so I'm not sure this is quite apples to oranges for comparing length.

    For the OP, I'm curious to know what about Perl6 makes this easier than Perl5. Or is that the point? Is the point just to play with perl6's new syntax?

    -xdg

    Code written by xdg and posted on PerlMonks is public domain. It is provided as is with no warranties, express or implied, of any kind. Posted code may not have been tested. Use of posted code is at your own risk.

      Oh, there's a three line non-recursive solution as well, using the same algorithm (as the recursive solution). I just find recursion much easier.
      sub cross { my @r = []; @r = map {my $l = $_; map {[@$_, $l]} @r} @$_ for @_; @r; }
      What I don't understand about the Perl6 solution is the need to count how many elements will be returned.
      Perl --((8:>*