diff options
| author | Abigail <abigail@abigail.be> | 2020-11-29 01:07:47 +0100 |
|---|---|---|
| committer | Abigail <abigail@abigail.be> | 2020-11-29 01:07:47 +0100 |
| commit | 9dfa59e83d71ded34b04ff78562abca8513966de (patch) | |
| tree | 4612d5c85d1ccf733993fecbd1f1d0d3996d518d | |
| parent | 4a5d33ddb0437322636b5a138f06ec8522338ce7 (diff) | |
| download | perlweeklychallenge-club-9dfa59e83d71ded34b04ff78562abca8513966de.tar.gz perlweeklychallenge-club-9dfa59e83d71ded34b04ff78562abca8513966de.tar.bz2 perlweeklychallenge-club-9dfa59e83d71ded34b04ff78562abca8513966de.zip | |
Week 88, part 2, Perl: Simplified the program.
We don't have to move a pointer step-by-step, we're processing
rows and columns, so we can just map{} got get a whole bunch.
| -rw-r--r-- | challenge-088/abigail/perl/ch-2.pl | 118 |
1 files changed, 36 insertions, 82 deletions
diff --git a/challenge-088/abigail/perl/ch-2.pl b/challenge-088/abigail/perl/ch-2.pl index 5455a70ed6..16f6c6f801 100644 --- a/challenge-088/abigail/perl/ch-2.pl +++ b/challenge-088/abigail/perl/ch-2.pl @@ -21,32 +21,15 @@ use experimental 'lexical_subs'; # We solve this by keeping track of the boundaries (min_x, min_y, max_x, # max_y) of the part of the matrix which still needs to be processed. # Initially, min_x and min_y are 0, max_x is the index of the bottom row, -# and max_y is the index of the right most column. The boundaries are -# stored in an array @boundaries, using indices $MIN_X, $MIN_Y, $MAX_X, -# $MAX_Y. +# and max_y is the index of the right most column. # -# We also keep track of the current position, that is, the position -# of the value which should be printed next. This starts off as (0, 0), -# the index of the top left corner. +# We then process the matrix side by side, first going east (top row), +# south (left column), west (bottom row), then north (left row). After +# doing a side, we update the corresponding min/max value. That is, +# after doing the top row, we increment $min_x; right column, decrement +# $max_y; bottom row, decrement $max_x; left column, increment $min_y. # -# Next thing we keep track of is the direction of travel, the change in -# (x, y) coordinate we take at each step. This will be initialized as -# (0, 1), as we start off moving to the right. -# -# We now move through the matrix in the direction of travel, printing -# the current value. If we hit the end of the yet-to-be-printed matrix, -# we rotate the direction of movement by 90 degrees, and update one of -# the boundaries: -# - If we have travelled the top row, we increment $min_x; -# - If we have travelled the right column, we decrement $max_y; -# - If we have travelled the bottom row, we decrement $max_x; -# - If we have travelled the left column, we increment $min_y. -# -# Note that we always travel the edges in the same order: -# top row (left to right), right edge (top to bottom), -# bottom row (right to left), left edge (bottom to top), and then repeat. -# -# We stop if $min_x > $max_x, or $min_y > $max_y. +# We're done when $min_x > $max_x, or $min_y > $max_y. # my @matrix = map {[/[1-9][0-9]*/g]} <>; @@ -56,71 +39,42 @@ my @matrix = map {[/[1-9][0-9]*/g]} <>; # die "Not a matrix" if grep {@$_ != @{$matrix [0]}} @matrix; -# -# Boundaries -# -my @boundaries; - $boundaries [my $MIN_X = 0] = 0; - $boundaries [my $MAX_Y = 1] = $#{$matrix [0]}; - $boundaries [my $MAX_X = 2] = $#matrix; - $boundaries [my $MIN_Y = 3] = 0; -my $boundary_change = 0; +my $EAST = 0; +my $SOUTH = 1; +my $WEST = 2; +my $NORTH = 3; -my $X = 0; -my $Y = 1; +my $direction = $EAST; -# -# Current pointer and direction. -# -my (@position, @direction); - @position [$X, $Y] = (0, 0); - @direction [$X, $Y] = (0, 1); +my $min_x = 0, +my $max_x = $#matrix; +my $min_y = 0; +my $max_y = $#{$matrix [0]}; -my $comma = ""; -while ($boundaries [$MIN_X] <= $boundaries [$MAX_X] && - $boundaries [$MIN_Y] <= $boundaries [$MAX_Y]) { - # - # Print the value at the current position. - # - print $comma, $matrix [$position [$X]] [$position [$Y]]; - $comma = ", "; - - # - # Where would we end up if we move one step. - # - my @next_position = ($position [$X] + $direction [$X], - $position [$Y] + $direction [$Y]); - - # - # Next if we're still in bounds. - # - if ($boundaries [$MIN_X] <= $next_position [$X] && - $next_position [$X] <= $boundaries [$MAX_X] && - $boundaries [$MIN_Y] <= $next_position [$Y] && - $next_position [$Y] <= $boundaries [$MAX_Y]) { - @position = @next_position; - next; +my @out; +while ($min_x <= $max_x && $min_y <= $max_y) { + if ($direction == $EAST) { + push @out => map {$matrix [$min_x] [$_]} $min_y .. $max_y; + $min_x ++; + } + elsif ($direction == $SOUTH) { + push @out => map {$matrix [$_] [$max_y]} $min_x .. $max_x; + $max_y --; + } + elsif ($direction == $WEST) { + push @out => reverse map {$matrix [$max_x] [$_]} $min_y .. $max_y; + $max_x --; + } + elsif ($direction == $NORTH) { + push @out => reverse map {$matrix [$_] [$min_y]} $min_x .. $max_x; + $min_y ++; } - # - # We're running off of the matrix, change direction, and - # update or decrement a minimum or maximum value. - # Note that we always hit boundaries in the same order. - # - $boundaries [$boundary_change] += ($boundary_change == 0 || - $boundary_change == 3) ? 1 : -1; - $boundary_change = ($boundary_change + 1) %4; - - # - # Rotate the movement direction 90 degrees clockwise, - # and update the position. - # - @direction = ($direction [$Y], -$direction [$X]); - @position = ($position [$X] + $direction [$X], - $position [$Y] + $direction [$Y]); + $direction = ($direction + 1) % ($NORTH + 1); } -print "\n"; +$, = ", "; +say @out; __END__ |
