aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAbigail <abigail@abigail.be>2020-11-29 21:08:00 +0100
committerAbigail <abigail@abigail.be>2020-11-29 21:08:00 +0100
commitd953b1ce25dbd354ab0a8a7b50a1b6adf4a36afa (patch)
tree06e97e0cab9f5629a92b6aca864adbbdccc99f32
parent9cf23023499954d50c7e31c078ef55771295cb3b (diff)
downloadperlweeklychallenge-club-d953b1ce25dbd354ab0a8a7b50a1b6adf4a36afa.tar.gz
perlweeklychallenge-club-d953b1ce25dbd354ab0a8a7b50a1b6adf4a36afa.tar.bz2
perlweeklychallenge-club-d953b1ce25dbd354ab0a8a7b50a1b6adf4a36afa.zip
C solution for week 88, part 2.
-rw-r--r--challenge-088/abigail/c/ch-2.c151
1 files changed, 151 insertions, 0 deletions
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);
+}