in reply to spiral path traversal for a grid

Here's what I came up with, using an iterator. I like the iterator because once it's written, you can kindof just forget about it. You could even throw the iterator in a different file, or module if need be. It's not the most elegant code, but it works, but there is no error checking. The iterator returns undef when it's done, but will start over if you call it again.

#!/usr/bin/perl my @box1 = ( [ qw/a b c d e f g/ ], [ qw/h i j k l m n/ ], [ qw/o p q r s t u/ ], ); my @box2 = ( [ qw/01 02 03 04 05 06 07/ ], [ qw/20 21 22 23 24 25 08/ ], [ qw/19 32 33 34 35 26 09/ ], [ qw/18 31 30 29 28 27 10/ ], [ qw/17 16 15 14 13 12 11/ ], ); my $iter1 = iterator( \@box1 ); while ( my $x = $iter1->() ) { print "$x "; } print "\n"; $iter2 = iterator( \@box2 ); while ( my $x = $iter2->() ) { print "$x "; } print "\n";
And now the iterator.
sub iterator { my $box = shift; # direction: # 0 => right # 1 => down # 2 => left # 3 => up my $direction = 0; my @pos = (0,0); my $up = 0; my $left = 0; my $down = ( scalar @$box ) - 1; my $right = ( scalar @{ $box->[0] } ) - 1; return sub { my $return_element = $box->[ $pos[1] ]->[ $pos[0] ]; if ( $up > $down or $left > $right ) { # reset, so if we call it after undef, it will start over. $up = 0; $left = 0; $down = ( scalar @$box ) - 1; $right = ( scalar @{ $box->[0] } ) - 1; @pos = ( 0, 0 ); $direction = 0; # return that we are done. return undef; } LABEL: { if ( $direction == 0 ) { if ( $pos[0] == $right ) { # we're traveling right and have hit the right edge. # change the direction to down. $direction++; # move our top edge (because we just got finished with # our uppermost remaining row) $up++; redo LABEL; } } if ( $direction == 1 ) { if ( $pos[1] == $down ) { # we're traveling down and have hit the bottom edge. # change the direction to left. $direction++; # move our right edge (because we just got finished wit +h # our rightmost remaining row) $right--; redo LABEL; } } if ( $direction == 2 ) { if ( $pos[0] == $left ) { # we're traveling left and have hit the leftmost edge. # change the direction to up. $direction++; # move our bottom edge (because we just got finished wi +th # our bottommost remaining row) $down--; redo LABEL; } } if ( $direction == 3 ) { if ( $pos[1] == $up ) { # we're traveling up and have hit the top edge. # change the direction to right. $direction=0; # move our left edge (because we just got finished with # our leftmost remaining row) $left++; redo LABEL; } } }; # move our position. if ( $direction == 0 ) { $pos[ 0 ]++; } elsif ( $direction == 1 ) { $pos[ 1 ]++; } elsif ( $direction == 2 ) { $pos[ 0 ]--; } elsif ( $direction == 3 ) { $pos[ 1 ]--; } return $return_element; } }

    -Bryan