aboutsummaryrefslogtreecommitdiff
path: root/challenge-088
diff options
context:
space:
mode:
authorMohammad S Anwar <mohammad.anwar@yahoo.com>2020-11-29 20:13:19 +0000
committerMohammad S Anwar <mohammad.anwar@yahoo.com>2020-11-29 20:13:19 +0000
commit3ceb28b64003e9d414a5efe5bc8f0a1e4c533ae6 (patch)
treefd5e8d76ab7695122400bb419e8b07dc56a6978b /challenge-088
parentd433b6e28a4d15e724a423272ded765b7d4eebc8 (diff)
parent15c864f39b1bef0ad6aa2ab433ec14400df97e3e (diff)
downloadperlweeklychallenge-club-3ceb28b64003e9d414a5efe5bc8f0a1e4c533ae6.tar.gz
perlweeklychallenge-club-3ceb28b64003e9d414a5efe5bc8f0a1e4c533ae6.tar.bz2
perlweeklychallenge-club-3ceb28b64003e9d414a5efe5bc8f0a1e4c533ae6.zip
Merge branch 'master' of https://github.com/manwar/perlweeklychallenge-club
Diffstat (limited to 'challenge-088')
-rw-r--r--challenge-088/abigail/blog1.txt1
-rw-r--r--challenge-088/abigail/c/ch-2.c151
-rw-r--r--challenge-088/abigail/node/ch-2.js96
-rw-r--r--challenge-088/abigail/perl/ch-2.pl118
4 files changed, 284 insertions, 82 deletions
diff --git a/challenge-088/abigail/blog1.txt b/challenge-088/abigail/blog1.txt
new file mode 100644
index 0000000000..ab782c48d9
--- /dev/null
+++ b/challenge-088/abigail/blog1.txt
@@ -0,0 +1 @@
+https://wp.me/pcxd30-8Z
diff --git a/challenge-088/abigail/c/ch-2.c b/challenge-088/abigail/c/ch-2.c
new file mode 100644
index 0000000000..91f52233f9
--- /dev/null
+++ b/challenge-088/abigail/c/ch-2.c
@@ -0,0 +1,151 @@
+# include <stdlib.h>
+# include <stdio.h>
+
+/*
+ * Challenge
+ *
+ * You are given m x n matrix of positive integers.
+ *
+ * Write a script to print spiral matrix as list.
+ */
+
+/*
+ * 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.
+ *
+ * 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.
+ *
+ * We're done when min_x > max_x, or min_y > max_y.
+ */
+
+typedef long long number;
+enum dirs {EAST, SOUTH, WEST, NORTH};
+
+int main (void) {
+ char * text = NULL; /* Complete input */
+ size_t buf_len = 0; /* Allocated buffer size */
+ ssize_t str_len; /* Number of characters read */
+ size_t rows = 0; /* Number of rows in matrix */
+ size_t columns = 0; /* Number of columns in matrix */
+ size_t elements = 0; /* Total number of elemenst in matrix */
+
+ number element; /* Element read */
+ int offset; /* Offset when scanning input */
+ char * ptr; /* Pointer into text */
+ number ** matrix; /* Matrix we're using */
+
+ enum dirs direction; /* Direction of movement */
+
+
+ /* Read all the input (this assumes the input doesn't contain *
+ * a NUL character. */
+ str_len = getdelim (&text, &buf_len, 0, stdin);
+
+ /* First, count the number of rows */
+ ptr = text;
+ while (*ptr) {
+ if (*ptr == '\n') {
+ rows ++;
+ }
+ ptr ++;
+ }
+
+ /* Count the number of elements */
+ ptr = text;
+ while (sscanf (ptr, "%lld%n", &element, &offset) == 1) {
+ elements ++;
+ ptr += offset;
+ }
+
+ /* We can now calculate the number of columns */
+ columns = elements / rows;
+
+ /* Check whether we have any elements left over; *
+ * if so, we exit with an error. */
+ if (elements != rows * columns) {
+ fprintf (stderr, "That doesn't look like a proper matrix\n");
+ exit (1);
+ }
+
+ /* Allocate memory */
+ if ((matrix = (number **) calloc (rows, sizeof (number *))) == NULL) {
+ fprintf (stderr, "Out of memory\n");
+ exit (1);
+ }
+
+ for (size_t x = 0; x < rows; x ++) {
+ if ((matrix [x] = (number *) calloc (columns,
+ sizeof (number))) == NULL) {
+ fprintf (stderr, "Out of memory\n");
+ exit (1);
+ }
+ }
+
+ /* Scan the text again, but now fill in the array */
+ ptr = text;
+ for (int x = 0; x < rows; x ++) {
+ for (int y = 0; y < columns; y ++) {
+ if (sscanf (ptr, "%lld%n", &matrix [x] [y], &offset) != 1) {
+ fprintf (stderr, "Something really weird happened!\n");
+ exit (1);
+ }
+ ptr += offset;
+ }
+ }
+
+ /* Now it's time to do the real work */
+ /* Note that we're using ssize_t for the min/max values; if we use *
+ * unsigned values, we're running into problems if we use a loop *
+ * counting down to zero. We would expect the loop to terminate if *
+ * the iterand is -1, but that cannot happen for an unsigned value. */
+ ssize_t min_x = 0;
+ ssize_t max_x = rows - 1;
+ ssize_t min_y = 0;
+ ssize_t max_y = columns - 1;
+
+ direction = EAST; /* We start off heading East */
+
+ size_t printed = 0; /* Each printed number will be preceeded by a *
+ * comma, except the first. */
+ while (min_x <= max_x && min_y <= max_y) {
+ if (direction == EAST) {
+ for (ssize_t y = min_y; y <= max_y; y ++) {
+ printf (printed ++ ? ", %lld" : "%lld", matrix [min_x] [y]);
+ }
+ min_x ++;
+ }
+ if (direction == SOUTH) {
+ for (ssize_t x = min_x; x <= max_x; x ++) {
+ printf (", %lld", matrix [x] [max_y]);
+ }
+ max_y --;
+ }
+ if (direction == WEST) {
+ for (ssize_t y = max_y; y >= min_y; y --) {
+ printf (", %lld", matrix [max_x] [y]);
+ }
+ max_x --;
+ }
+ if (direction == NORTH) {
+ for (ssize_t x = max_x; x >= min_x; x --) {
+ printf (", %lld", matrix [x] [min_y]);
+ }
+ min_y ++;
+ }
+ direction = (direction + 1) % (NORTH + 1);
+ }
+ printf ("\n");
+
+ /* Clean up the allocated memory */
+ for (size_t x = 0; x < rows; x ++) {
+ free (matrix [x]);
+ }
+ free (matrix);
+ free (text);
+}
diff --git a/challenge-088/abigail/node/ch-2.js b/challenge-088/abigail/node/ch-2.js
new file mode 100644
index 0000000000..ee99a7cf07
--- /dev/null
+++ b/challenge-088/abigail/node/ch-2.js
@@ -0,0 +1,96 @@
+//
+// Challenge
+//
+// You are given m x n matrix of positive integers.
+//
+// Write a script to print spiral matrix as list.
+//
+
+//
+// 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.
+//
+// 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.
+//
+// We're done when min_x > max_x, or min_y > max_y.
+//
+
+//
+// Read STDIN. Split on newlines, then on white space.
+//
+let matrix = require ("fs")
+ . readFileSync (0) // Read all.
+ . toString () // Turn it into a string.
+ . split ("\n") // Split on newlines.
+ . filter (_ => _ . length) // Filter empty lines.
+ . map (_ => _ . trim () // Trim white space.
+ . split (/\s+/)) // Split on whitespace.
+;
+
+//
+// Check if all rows are the same length
+//
+matrix . forEach (row => {
+ if (row . length != matrix [0] . length) {
+ throw "Not all rows are of equal length";
+ }
+});
+
+//
+// Set some variables
+//
+let EAST = 0;
+let SOUTH = 1;
+let WEST = 2;
+let NORTH = 3;
+
+let direction = EAST; // Initial direction
+
+let min_x = 0;
+let max_x = matrix . length - 1;
+let min_y = 0;
+let max_y = matrix [0] . length - 1;
+
+//
+// Spiral down the matrix, putting the results into the string output.
+//
+let output = "";
+while (min_x <= max_x && min_y <= max_y) {
+ if (direction == EAST) {
+ for (let y = min_y; y <= max_y; y ++) {
+ output = output + ", " + matrix [min_x] [y];
+ }
+ min_x ++;
+ }
+ if (direction == SOUTH) {
+ for (let x = min_x; x <= max_x; x ++) {
+ output = output + ", " + matrix [x] [max_y];
+ }
+ max_y --;
+ }
+ if (direction == WEST) {
+ for (let y = max_y; y >= min_y; y --) {
+ output = output + ", " + matrix [max_x] [y];
+ }
+ max_x --;
+ }
+ if (direction == NORTH) {
+ for (let x = max_x; x >= min_x; x --) {
+ output = output + ", " + matrix [x] [min_y];
+ }
+ min_y ++;
+ }
+
+ direction = (direction + 1) % (NORTH + 1);
+}
+
+//
+// Print the result, without the leading ", ".
+//
+process . stdout . write (output . slice (2) + "\n");
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__