aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAbigail <abigail@abigail.be>2020-11-29 01:07:47 +0100
committerAbigail <abigail@abigail.be>2020-11-29 01:07:47 +0100
commit9dfa59e83d71ded34b04ff78562abca8513966de (patch)
tree4612d5c85d1ccf733993fecbd1f1d0d3996d518d
parent4a5d33ddb0437322636b5a138f06ec8522338ce7 (diff)
downloadperlweeklychallenge-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.pl118
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__