From d953b1ce25dbd354ab0a8a7b50a1b6adf4a36afa Mon Sep 17 00:00:00 2001 From: Abigail Date: Sun, 29 Nov 2020 21:08:00 +0100 Subject: C solution for week 88, part 2. --- challenge-088/abigail/c/ch-2.c | 151 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 151 insertions(+) create mode 100644 challenge-088/abigail/c/ch-2.c 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 +# include + +/* + * 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); +} -- cgit