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

Hi, Going up $line:
for my $i (2..3) { for my $line (0..4**$i) {
Would like to report (for level $i=2, 16 lines)
line 0 - 0,0
line 1 - 0,1
line 2 - 0,2
line 3 - 0,3
line 4 - 1,0
line 5 - 1,1 (...) line 15 - 3,3

for level ($i=3, 64 lines)
line 0 - 0,0,0
line 1 - 0,0,1
line 2 - 0,0,2
line 3 - 0,0,3
line 4 - 0,1,0 (...) line 63 - 3,3,3

And so on for larger $i.
Thanks, best.

Replies are listed 'Best First'.
Re: Incremental indexing exponential
by ikegami (Patriarch) on Jun 21, 2007 at 15:48 UTC
    Variable number of nested loops begs for Algorithm::Loops's NestedLoops.
    use Algorithm::Loops qw( NestedLoops ); for my $depth (2..3) { NestedLoops( [ ([ 0..3 ]) x $depth ], sub { print(join(', ', @_), "\n"); }, ); }
      Thanks ikegami, this works excellent. NestedLoops again :-)
Re: Incremental indexing exponential
by shmem (Chancellor) on Jun 21, 2007 at 15:43 UTC
    Homework?
    Elegant suggestions on how to code (i.e. report index while going up $line)?
    You first... :-P

    Show some effort. See How (Not) To Ask A Question.

    --shmem

    _($_=" "x(1<<5)."?\n".q·/)Oo.  G°\        /
                                  /\_¯/(q    /
    ----------------------------  \__(m.====·.(_("always off the crowd"))."·
    ");sub _{s./.($e="'Itrs `mnsgdq Gdbj O`qkdq")=~y/"-y/#-z/;$e.e && print}
Re: Incremental indexing exponential
by RMGir (Prior) on Jun 21, 2007 at 15:45 UTC
    Interesting.

    Not sure how elegant this is, but it's easy if you compute the elements of your sets of numbers from last to first:

    for my $i (2..3) { local $/=","; for my $line (0..4**$i - 1) { # you were missing -1 print "line $line - "; my $num=$line; my @tuple; for my $j (0..$i-1) { unshift @tuple, $num%4; $num/=4; } print "@tuple\n"; } }

    Mike
Re: Incremental indexing exponential
by ikegami (Patriarch) on Jun 21, 2007 at 15:59 UTC

    You can think of $line as a base 4 number.

    $line = $digits[0] * 4**0 + $digits[1] * 4**1 + $digits[2] * 4**2

    That can also be written as

    $line = ($digits[2] * 4 + $digits[1]) * 4 + $digits[0]

    You can use modulo and division

    for my $num_digits (2..3) { for my $line (0 .. 4**$num_digits - 1) { my $remain = $line; my @digits; for (1..$depth) { push @digits, $remain % 4; $remain = int($remain / 4); } print(join(', ', @digits), "\n"); } }

    Since 4 is a power of two, bit arithmetic can be used instead.

    push @digits, $remain & 3; $remain >>= 2;
      I think your solution would get the digits reversed from the homework question spec.

      Mike

        Keeping in line with the base4 methaphor, I placed the lower-precedence digits at the lower indexes in @digits. Feel free to change the order in which they are stored (by substituting unshift for push) or to change the order in which they are printed (by using reverse, by iterating over them in reverse order, or ...).

Re: Incremental indexing exponential
by whereiskurt (Friar) on Jun 21, 2007 at 16:39 UTC

    I tried to get this to you earlier, but I couldn't get the 'push @{$prec}' working because I thought it was an array (not an arrayref. :\ )

    This code is along the lines of 'Aren't you really just counting up to a number using base 4?'

    use Math::BaseArith; my $base = 4; #Start with 2 digits of precision my $prec = [$base, $base]; for my $i (2..3) { my $max = ($base ** $i); PREC: for my $line (0..4**$i) { last PREC if ($line >= $max ); #Check for overflow print encode( $line, $prec), "\n"; } push @{$prec}, $base; #+Another digit of precision. }

    That was kind of fun!

    Update: Made numeric comp (>=), and corrected max.

    Kurt