Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

how to permute multi arrays with different numbers of element?

2 views
Skip to first unread message

VZD

unread,
Mar 9, 2012, 5:30:33 PM3/9/12
to
Please help me to solve problem, how to permute multi arrays with different
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";
}
}
}




Kiuhnm

unread,
Mar 9, 2012, 7:01:13 PM3/9/12
to
On 3/9/2012 23:30, VZD wrote:
> Please help me to solve problem, how to permute multi arrays with different
> numbers of element? I can make it manually, but what If you have more that
> three arrays?

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

Dr.Ruud

unread,
Mar 9, 2012, 7:55:04 PM3/9/12
to
On 2012-03-09 23:30, VZD wrote:

> Please help me to solve problem, how to permute multi arrays with different
> numbers of element? I can make it manually, but what If you have more that
> three arrays?

Check out `perldoc -f glob`.


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

Numbered names raise a red flag.

--
Ruud

Randal L. Schwartz

unread,
Mar 9, 2012, 8:15:34 PM3/9/12
to
>>>>> "Ruud" == Ruud <rvtol+...@xs4all.nl> writes:

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

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
<mer...@stonehenge.com> <URL:http://www.stonehenge.com/merlyn/>
Smalltalk/Perl/Unix consulting, Technical writing, Comedy, etc. etc.
See http://methodsandmessages.posterous.com/ for Smalltalk discussion

Alan Curry

unread,
Mar 9, 2012, 9:55:36 PM3/9/12
to
This operation is called a "Cartesian product". Knowing that, it should be
easy to find several implementations.

--
Alan Curry

Ben Morrow

unread,
Mar 9, 2012, 10:07:51 PM3/9/12
to

Quoth "VZD" <v...@vzd.vzd>:
> Please help me to solve problem, how to permute multi arrays with different
> numbers of element? I can make it manually, but what If you have more that
> three arrays?

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

Martijn Lievaart

unread,
Mar 10, 2012, 2:05:54 AM3/10/12
to
On Sat, 10 Mar 2012 03:07:51 +0000, Ben Morrow wrote:

> (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.)

I like it. Makes perfect sense.

M4

Kiuhnm

unread,
Mar 10, 2012, 6:19:16 AM3/10/12
to
It depends on what VZD really wants. Does he want the elements in that
precise order?

Kiuhnm

Kiuhnm

unread,
Mar 10, 2012, 6:24:29 AM3/10/12
to
On 3/10/2012 4:07, Ben Morrow wrote:
> (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.)

That should apply to all list operators.

Kiuhnm

Dr.Ruud

unread,
Mar 10, 2012, 10:19:40 AM3/10/12
to
On 2012-03-10 04:07, Ben Morrow wrote:
> Quoth "VZD"<v...@vzd.vzd>:

>> Please help me to solve problem, how to permute multi arrays with different
>> numbers of element? I can make it manually, but what If you have more that
>> three arrays?
>
> Hmm, well, since noone's given the obvious answer yet...

Was glob too obvious?

perl -wle'print for glob "{1,2,3}{4,5,6}{7,8}"'

--
Ruud

Dr.Ruud

unread,
Mar 10, 2012, 10:37:32 AM3/10/12
to
On 2012-03-10 02:15, Randal L. Schwartz wrote:
> Ruud:
>> vdz:

>>> my @digits1 = qw(1 2);
>>> my @digits2 = qw(1 2);
>>> my @digits3 = qw(a b c);
>>
>> Numbered names raise a red flag.
>
> Some call it "code smell". I like that.

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

Ben Morrow

unread,
Mar 10, 2012, 11:10:50 AM3/10/12
to

Quoth "Dr.Ruud" <rvtol+...@xs4all.nl>:
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

xho...@gmail.com

unread,
Mar 10, 2012, 11:51:18 AM3/10/12
to
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

--
-------------------- http://NewsReader.Com/ --------------------
The costs of publication of this article were defrayed in part by the
payment of page charges. This article must therefore be hereby marked
advertisement in accordance with 18 U.S.C. Section 1734 solely to indicate
this fact.

Dr.Ruud

unread,
Mar 10, 2012, 11:51:32 AM3/10/12
to
On 2012-03-10 17:10, Ben Morrow wrote:
> Ruud:
>> Ben:
>>> vdz:

>>>> Please help me to solve problem, how to permute multi arrays with
>>>> different numbers of element? I can make it manually, but what If
>>>> you have more that three arrays?
>>>
>>> Hmm, well, since noone's given the obvious answer yet...
>>
>> Was glob too obvious?
>>
>> perl -wle'print for glob "{1,2,3}{4,5,6}{7,8}"'
>
> 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.

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

Dr.Ruud

unread,
Mar 10, 2012, 12:13:25 PM3/10/12
to
On 2012-03-10 17:51, xho...@gmail.com wrote:
> "Dr.Ruud"<rvtol+...@xs4all.nl> wrote:

>> perl -wle'print for glob "{1,2,3}{4,5,6}{7,8}"'
>
> 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.

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

Ben Morrow

unread,
Mar 10, 2012, 12:33:43 PM3/10/12
to

Quoth "Dr.Ruud" <rvtol+...@xs4all.nl>:
Let's have a look, shall we?

~% ktrace -tn perl -e'glob "{1,2}{3,4}"'
~% 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

Kiuhnm

unread,
Mar 10, 2012, 1:10:53 PM3/10/12
to
On 3/10/2012 4:07, Ben Morrow wrote:
> 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;

Here's a more efficient version:

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

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

Kiuhnm

Dr.Ruud

unread,
Mar 10, 2012, 1:23:35 PM3/10/12
to
On 2012-03-10 18:33, Ben Morrow wrote:
> Ruud:
>> xhoster:

>>> 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.
>>
>> 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>
>
> Let's have a look, shall we?
>
> ~% ktrace -tn perl -e'glob "{1,2}{3,4}"'
> ~% 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.)

Bug?

--
Ruud

Peter J. Holzer

unread,
Mar 10, 2012, 3:04:44 PM3/10/12
to
On 2012-03-10 17:13, Dr.Ruud <rvtol+...@xs4all.nl> wrote:
> On 2012-03-10 17:51, xho...@gmail.com wrote:
>> "Dr.Ruud"<rvtol+...@xs4all.nl> wrote:
>
>>> perl -wle'print for glob "{1,2,3}{4,5,6}{7,8}"'
>>
>> 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.
>
> Why do you think it would go to disk?

Because older ones *do* go to disk?

% strace perl -wle'print for glob "{1,2,3}{4,5,6}{7,8}"'
[...]
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)

Copyright 1987-2009, Larry Wall


><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>

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.
| | | h...@hjp.at |
__/ | http://www.hjp.at/ | -- Bill Code on as...@irtf.org
0 new messages