# how to permute multi arrays with different numbers of element?

#### Do you have a question? Post it now! No Registration Necessary.  Now with pictures!

•  Subject
• Author
• Posted on
numbers of element? I can make it manually, but what If you have more that
three arrays?

Thanks

# Perl permute multidimensional arrays
#

my @digits1 = qw(1 2);
my @digits2 = qw(1 2);
my @digits3 = qw(a b c);

foreach my \$i (@digits1) {
foreach my \$j (@digits2) {
foreach my \$k (@digits3) {
print "\$i\$j\$k\$l\n";
}
}
}

## Re: how to permute multi arrays with different numbers of element?

On 3/9/2012 23:30, VZD wrote:

Here's an iterative way:

--->
sub count {
my \$cback = shift;
my @sizes = @_;
my @cnts = map { 0 } 0..\$#sizes;

\$cback->(@cnts);
while (1) {
my \$idx = \$#cnts;
\$cnts[\$idx]++;
while (\$idx > 0) {
last if \$cnts[\$idx] < \$sizes[\$idx];
\$cnts[\$idx] = 0;
\$cnts[--\$idx]++;
}
last if (!\$idx && \$cnts[0] == \$sizes[0]);
\$cback->(@cnts);
}
}

my @digits1 = qw(1 2);
my @digits2 = qw(1 2);
my @digits3 = qw(a b c);

my @arrays = (\@digits1, \@digits2, \@digits3);
&count(sub { say map { \$arrays[\$_]->[\$_[\$_]] } 0..\$#arrays },
map { scalar @ } @arrays);
<---

Kiuhnm

## Re: how to permute multi arrays with different numbers of element?

On 2012-03-09 23:30, VZD wrote:

Check out `perldoc -f glob`.

Numbered names raise a red flag.

--
Ruud

## Re: how to permute multi arrays with different numbers of element?

Ruud> Numbered names raise a red flag.

Some call it "code smell".  I like that.

--
Randal L. Schwartz - Stonehenge Consulting Services, Inc. - +1 503 777 0095
Smalltalk/Perl/Unix consulting, Technical writing, Comedy, etc. etc.
See http://methodsandmessages.posterous.com/ for Smalltalk discussion

## Re: how to permute multi arrays with different numbers of element?

On 2012-03-10 02:15, Randal L. Schwartz wrote:

>> vdz:

1. Numbered names smell.
2. Numbered names are code smell.
3. Numbered names make your code smell.
4. Code with numbered names smells.

I still prefer my n-n r-r pattern.
(I would translate "pink panther" to "paarse panter",
though "pink" is normally "roze".)

--
Ruud

## Re: how to permute multi arrays with different numbers of element?

This operation is called a "Cartesian product". Knowing that, it should be
easy to find several implementations.

--
Alan Curry

## Re: how to permute multi arrays with different numbers of element?

On 3/10/2012 3:55, Alan Curry wrote:

It depends on what VZD really wants. Does he want the elements in that
precise order?

Kiuhnm

## Re: how to permute multi arrays with different numbers of element?

Hmm, well, since noone's given the obvious answer yet...

my @digits = (
[1, 2, 3],
[4, 5, 6],
[7, 8],
);

sub permute {
map {
my \$d = \$_;
@_ ? map "\$d\$_", permute(@_) : \$d;
} @{ +shift };
}

say for permute @digits;

Of course, you'll learn a lot more if you do your own homework.

(I seem to keep finding situations where I want to be able to say

map my \$d { ... } ...

, and I believe the 'my' is enough to stop it being ambiguous. Hmmm.)

Ben

## Re: how to permute multi arrays with different numbers of element?

On Sat, 10 Mar 2012 03:07:51 +0000, Ben Morrow wrote:

I like it. Makes perfect sense.

M4

## Re: how to permute multi arrays with different numbers of element?

On 3/10/2012 4:07, Ben Morrow wrote:

That should apply to all list operators.

Kiuhnm

## Re: how to permute multi arrays with different numbers of element?

On 2012-03-10 04:07, Ben Morrow wrote:

Was glob too obvious?

perl -wle'print for glob ""'

--
Ruud

## Re: how to permute multi arrays with different numbers of element?

glob doesn't work with arbitrary strings. I suppose you could assume the
OP was only (ever going to be) permuting digits, but I generally dislike
solutions that involve quoting and reparsing. Besides, the question
asked for an arbtrary number of arrays, and I don't know that

glob join "",
map "",
map { join ",", @\$_ }
@digits;

is much more concise than the solution I posted.

Ben

## Re: how to permute multi arrays with different numbers of element?

On 2012-03-10 17:10, Ben Morrow wrote:

Good points. It easily gets ugly:

perl -wle '
my @digits = ( [ 1, 2, 3 ], [ 4, 5, 6 ], [ 7, "8,X" ] );
print for glob join "",
map "",
map join( ",", map quotemeta, @\$_ ),
@digits;
'

--
Ruud

## Re: how to permute multi arrays with different numbers of element?

I haven't tried this on a newer perl, but at least on older ones this
method will get slow and beat the crap out of your hard drive as the list
gets longs.  It checks whether each string exists as a filename, but the
results of that check are ignored.

Xho

--
The costs of publication of this article were defrayed in part by the
this fact.

## Re: how to permute multi arrays with different numbers of element?

On 2012-03-10 17:51, xhoster@gmail.com wrote:

Why do you think it would go to disk?

<quote src=`perldoc -f glob`>
If non-empty braces are the only wildcard characters used in
the "glob", no filenames are matched, but potentially many
strings are returned.
</quote>

Still, see Ben's reasons to avoid glob.

--
Ruud

## Re: how to permute multi arrays with different numbers of element?

Let's have a look, shall we?

~% ktrace -tn perl -e'glob ""'
~% kdump
<snip>
34066 perl     NAMI  "13"
34066 perl     NAMI  "14"
34066 perl     NAMI  "23"
34066 perl     NAMI  "24"
~%

So, yes, it goes to the disk, whether it needed to or not. (This is
5.12.2.)

Ben

## Re: how to permute multi arrays with different numbers of element?

On 2012-03-10 18:33, Ben Morrow wrote:

Bug?

--
Ruud

## Re: how to permute multi arrays with different numbers of element?

^^^^^^^^^^

Because older ones *do* go to disk?

% strace perl -wle'print for glob ""'
[...]
lstat64("147", 0xbf910610)              = -1 ENOENT (No such file or directory)
lstat64("148", 0xbf910610)              = -1 ENOENT (No such file or directory)
lstat64("157", 0xbf910610)              = -1 ENOENT (No such file or directory)
lstat64("158", 0xbf910610)              = -1 ENOENT (No such file or directory)
lstat64("167", 0xbf910610)              = -1 ENOENT (No such file or directory)
lstat64("168", 0xbf910610)              = -1 ENOENT (No such file or directory)
lstat64("247", 0xbf910610)              = -1 ENOENT (No such file or directory)
lstat64("248", 0xbf910610)              = -1 ENOENT (No such file or directory)
lstat64("257", 0xbf910610)              = -1 ENOENT (No such file or directory)
lstat64("258", 0xbf910610)              = -1 ENOENT (No such file or directory)
lstat64("267", 0xbf910610)              = -1 ENOENT (No such file or directory)
lstat64("268", 0xbf910610)              = -1 ENOENT (No such file or directory)
lstat64("347", 0xbf910610)              = -1 ENOENT (No such file or directory)
lstat64("348", 0xbf910610)              = -1 ENOENT (No such file or directory)
lstat64("357", 0xbf910610)              = -1 ENOENT (No such file or directory)
lstat64("358", 0xbf910610)              = -1 ENOENT (No such file or directory)
lstat64("367", 0xbf910610)              = -1 ENOENT (No such file or directory)
lstat64("368", 0xbf910610)              = -1 ENOENT (No such file or directory)
write(1, "147\n", 4147
)                    = 4
write(1, "148\n", 4148
)                    = 4
write(1, "157\n", 4157
)                    = 4
[...]

% perl -v

This is perl, v5.10.1 (*) built for i486-linux-gnu-thread-multi
(with 56 registered patches, see perl -V for more detail)

This sentence isn't there in 5.10.1. If newer perls don't try to stat
the files any more (note that "no filenames are matched" doesn't
necessarily imply this), then the change was made after 5.10.1

hp

--
_  | Peter J. Holzer    | Deprecating human carelessness and
|_|_) | Sysadmin WSR       | ignorance has no successful track record.
| |   | hjp@hjp.at         |
__/   | http://www.hjp.at/ |  -- Bill Code on asrg@irtf.org

## Re: how to permute multi arrays with different numbers of element?

On 3/10/2012 4:07, Ben Morrow wrote:

Here's a more efficient version:

--->
sub count {
my \$str = shift;
for (@) {
@_ ? count("\$str\$_", @_) : say "\$str\$_"
}
}

count("", @digits);
<---

Kiuhnm