liri has asked for the wisdom of the Perl Monks concerning the following question:

is it possible to have a dynamic number of arrays with dynamic number of elements in it and come up with a matrix
of all combinations available (through-out all the arrays elements).


i.e:
1 5 7
2 3 4
5 1 9
7 8
3


there can be more than 3 columns and the number of elements is also dynamic.

Replies are listed 'Best First'.
Re: dynamic matrix
by tirwhan (Abbot) on Dec 19, 2005 at 15:14 UTC
    @matrix =([1,5,7], [2,3,4], [5,1,9], [7,8], [3]); for my $y(0..$#matrix) { my @row=@{$matrix[$y]}; for my $x(0..$#row) { print "Value $row[$x] at x $x y $y\n"; } }

    Update: tphyahoo feels that the syntax would be more obvious if I used only array references here instead of arrays and I sorta agree (I think it runs the risk of encouraging cargo cult programming, because someone who doesn't understand references can think they know what's going on without understanding the underlying data structure), so here's a version with just references:

    $matrix =[ [1,5,7], [2,3,4], [5,1,9], [7,8], [3] ]; for my $y(0..$#{$matrix}) { for my $x(0..$#{$matrix->[$y]}){ print "Value $matrix->[$y]->[$x] at y $y x $x\n"; } }

    Debugging is twice as hard as writing the code in the first place. Therefore, if you write the code as cleverly as possible, you are, by definition, not smart enough to debug it. -- Brian W. Kernighan
Re: dynamic matrix
by Fletch (Bishop) on Dec 19, 2005 at 15:38 UTC

    You may also be interested in PDL if you really do want a matrix in the mathematical sense and are planing to do Real Math™ with it.

Re: dynamic matrix
by neosamuri (Friar) on Dec 19, 2005 at 15:35 UTC

    I thought I would give a little more information on what is going on in the example above. The matrix is a array of array references. Each ref is not restricted to the size of the other refs. you can also resize arrays by adding more members or removing them. for further reading i would suggest reading the perlref. Hopefully this was helpful.

Re: dynamic matrix
by tphyahoo (Vicar) on Dec 19, 2005 at 15:47 UTC
    See Re: text processing - convert list of vectors to tabular format for a variation on this theme that uses $table->[$horiz]->[$vert] type syntax, which to my mind seems more "matrixlike" than tirwan's solution above. I think this way it is easier to grab the horizontal vectors if that's what you want to do, or the verticals if you want them. Whereas in tirwan's solution , feels to me like one axis is "preferred." (The horizontal vectors.)

      Well, all you need to do to use the same syntax with my solution is

      $table=\@matrix;

      Debugging is twice as hard as writing the code in the first place. Therefore, if you write the code as cleverly as possible, you are, by definition, not smart enough to debug it. -- Brian W. Kernighan
        True. And thanks for pointing that out, enlightening. However, I still feel like
        my $matrix =[ [1,5,7], [2,3,4], [5,1,9], [7,8], [3] ] ;
        feels more "aesthetically" right than setting it up with @matrix like you did above, and then $matrix = \@matrix... even if both are equivalent.
Re: dynamic matrix
by ambrus (Abbot) on Dec 20, 2005 at 14:43 UTC

    Hi. Your question isn't really clear to me, but I guess you want a cartesian product. For example, with the input you gave, I think you want the output

    1 5 7 1 5 4 1 5 9 1 3 7 1 3 4 ... 3 8 4 3 8 9
    That's a problem I've met quite a few times but I always find it hard to implement them (especially the more complicated versions. Here is a solution:
    use warnings; use strict; sub cartesian_product { @_ or return []; my @last = @{pop()}; map { my @x = @$_; map { [@x, $_] } @last } cartesian_product( +@_); } my @columns = ([1, 2, 5, 7, 3], [5, 3, 1, 8], [7, 4, 9]); my @r = cartesian_product(@columns); for (@r) { print join(" ", @$_), "\n"; } __END__