Steve (another one) <> wrote in comp.lang.perl.misc:
> John W. Krahn wrote:
> > "Steve (another one)" wrote:
> >
> >>I have just wasted a crazy amount of time trying to populate an array
> >>containing every combination of n values at y positions. It feels as
> >>though it should be trivial and the sort of thing I do every day, but in
> >>fact I could not find the simple solution that surely must exist.
> >>
> >>Below is my best attempt - it will also explain the task if I haven't
> >>been clear - can someone tell me if there is a simpler way of doing it.
> >>
> >>[snip]
> >
> >
> > You could do it like this:
> >
> > #!/usr/bin/perl
> > use warnings;
> > use strict;
> >
> > my $min_value = 1;
> > my $max_value = 4;
> > my $number_of_positions = 3;
> >
> > my $glob = ( '{' . join( ',', $min_value .. $max_value ) . '}' ) x
> $number_of_positions;
> >
> > $individual = 0;
> > print $individual++, " - @$_\n" for map [ /./g ], glob $glob;
> >
> > __END__
> >
> >
> > 
> >
> > John
> cool, what a brilliant way to do it
It can also be considered a counting problem.
Consider the number system whose base is $base = $max_value - $min_value + 1.
Enumerate all numbers with $number_of_positions digits in this system.
(There will be $base**$number_of_positions such numbers.) Increment each
digit individually by $min_value. That yields the required set of
combinations.
The glob is a clever hack that does the required counting. A more
direct way is this:
my @digits = ( $min_value) x $number_of_positions;
my $individual = 0;
while ( 1 ) {
print $individual++, " - @digits\n";
last unless grep $_ < $max_value, @digits;
for ( reverse @digits ) { # increment with carry
last if ++ $_ <= $max_value;
$_ = $min_value;
}
}
Anno