From a56b3551c19e4fb3a860d86bc2bf3e18a68080d9 Mon Sep 17 00:00:00 2001 From: Adam Spragg Date: Mon, 2 Jan 2023 11:30:27 +0000 Subject: Puzzle 22: Create "elf" type to hold position and orientation This will help when just moving around can change the orientation, as you move over an edge --- 22.c | 74 ++++++++++++++++++++++++++++++++++++++++---------------------------- 1 file changed, 44 insertions(+), 30 deletions(-) diff --git a/22.c b/22.c index 706d62a..f29f78e 100644 --- a/22.c +++ b/22.c @@ -32,42 +32,55 @@ direction_name(enum direction dir) } -enum direction -direction_turn(enum direction dir, char turn) +struct elf { + long pos; + enum direction dir; +}; + + +int +elf_turn(struct elf * elf, char turn) { #define direction_go(d, t) (1000 * (d) + (t)) - switch (direction_go(dir, turn)) { + switch (direction_go(elf->dir, turn)) { case direction_go(D_NORTH, 'R'): case direction_go(D_SOUTH, 'L'): - return D_EAST; + elf->dir = D_EAST; + break; case direction_go(D_NORTH, 'L'): case direction_go(D_SOUTH, 'R'): - return D_WEST; + elf->dir = D_WEST; + break; case direction_go(D_EAST, 'L'): case direction_go(D_WEST, 'R'): - return D_NORTH; + elf->dir = D_NORTH; + break; case direction_go(D_EAST, 'R'): case direction_go(D_WEST, 'L'): - return D_SOUTH; + elf->dir = D_SOUTH; + break; + + default: + fprintf(stderr, "Unexpected elf_turn(%d, %c)\n", elf->dir, turn); + return -1; } - fprintf(stderr, "Unexpected direction_turn(%d, %c)\n", dir, turn); - return D_NORTH; + return 0; #undef direction_go } int -map_move(char * map, int cols, int rows, int pos, enum direction dir, int distance) +elf_move(struct elf * elf, char const * map, int cols, int rows, int distance) { int skip, wrap, base; - switch (dir) { + switch (elf->dir) { case D_NORTH: skip = -cols; wrap = cols * rows; @@ -89,21 +102,21 @@ map_move(char * map, int cols, int rows, int pos, enum direction dir, int distan break; default: - fprintf(stderr, "Unexpected direction %d\n", dir); + fprintf(stderr, "Unexpected direction %d\n", elf->dir); return -1; } - base = (pos / wrap) * wrap; + base = (elf->pos / wrap) * wrap; while (distance > 0) { - int newpos = base + modulo(pos + skip, wrap); + int newpos = base + modulo(elf->pos + skip, wrap); while (map[newpos] == ' ' || map[newpos] == '\n') newpos = base + modulo(newpos + skip, wrap); switch (map[newpos]) { case '.': - pos = newpos; + elf->pos = newpos; --distance; break; @@ -117,7 +130,7 @@ map_move(char * map, int cols, int rows, int pos, enum direction dir, int distan } } - return pos; + return 0; } @@ -127,11 +140,10 @@ main() char * buf = NULL, * beg, * end; long bufsiz = 0, buflen = 0, maxline = 0, lines = 0; long pos; - enum direction dir; + struct elf elf; char distance[8], c; int dlen = 0; - // Read map data // Don't try and figure out lines yet, in case we get a line longer than // our read buffer, which could make things awkward. @@ -190,29 +202,31 @@ main() } // Set initial position - pos = 0; - dir = D_EAST; - while (buf[pos] != '.') { - ++pos; - } + elf.pos = 0; + elf.dir = D_EAST; + while (buf[elf.pos] != '.') + ++elf.pos; // Read and follow the movement instructions. - while (pos >= 0 && (c = fgetc(stdin)) != EOF) { + while (elf.pos >= 0 && (c = fgetc(stdin)) != EOF) { if (isdigit(c)) { distance[dlen++] = c; } else if (c == 'L' || c == 'R') { distance[dlen] = '\0'; - pos = map_move(buf, maxline, lines, pos, dir, atoi(distance)); + if (elf_move(&elf, buf, maxline, lines, atoi(distance)) != 0) + elf.pos = -1; + if (elf_turn(&elf, c) != 0) + elf.pos = -1; - dir = direction_turn(dir, c); dlen = 0; } else if (c == '\n') { // Cover last bit of distance, if any distance[dlen] = '\0'; - pos = map_move(buf, maxline, lines, pos, dir, atoi(distance)); + if (elf_move(&elf, buf, maxline, lines, atoi(distance)) != 0) + elf.pos = -1; break; } else { @@ -221,15 +235,15 @@ main() return -1; } } - if (pos < 0) { + if (elf.pos < 0) { free(buf); return -1; } // Done. printf("Password is %ld (%ld,%ld,%d)\n", - 1000 * (1 + pos / maxline) + 4 * (1 + pos % maxline) + dir, - (1 + pos % maxline), (1 + pos / maxline), dir); + 1000 * (1 + elf.pos / maxline) + 4 * (1 + elf.pos % maxline) + elf.dir, + (1 + elf.pos % maxline), (1 + elf.pos / maxline), elf.dir); // Tidy and exit. free(buf); -- cgit v1.2.1