summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAdam Spragg <adam@spra.gg>2023-01-02 11:30:27 +0000
committerAdam Spragg <adam@spra.gg>2023-01-02 11:30:27 +0000
commita56b3551c19e4fb3a860d86bc2bf3e18a68080d9 (patch)
tree0dccd2bd3af5f63ee2d1303405cedc06c35597f6
parenta51a6be8d5f1614e0cdf696c2d1cb57354a1c500 (diff)
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
-rw-r--r--22.c74
1 files 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);