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


In reply to Re: spiral path traversal for a grid by mrborisguy
in thread spiral path traversal for a grid by frenchtoast

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post, it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.