#include #include #include /* A place for carts to go */ #define MAX_WIDTH 256 #define MAX_HEIGHT 256 static char playfield[MAX_HEIGHT][MAX_WIDTH]; /* Some carts to go in the place */ #define MAX_CARTS 256 static int num_carts = 0; static struct cart { short x; short y; char dir; char turn; char under; char crashed; } carts[MAX_CARTS]; static const char cart_symbols[] = ">^crashed - cart_b->crashed; if (!result) result = cart_a->y - cart_b->y; if (!result) result = cart_a->x - cart_b->x; return result; } /* Sort carts */ void sort_carts() { qsort(carts, num_carts, sizeof (struct cart), cartcmp); } /* A way to look at all that stuff */ void show_playfield() { for (char *p = *playfield; *p; p += MAX_WIDTH) { printf("%s", p); } putchar('\n'); } void show_carts() { if (num_carts) { for (int i = 0; i < num_carts; i++) { struct cart *p = &carts[i]; if (p->crashed) putchar('!'); printf("%d,%d%c%c%c ", p->x, p->y, cart_symbols[p->dir], cart_turns[p->turn], p->under ); } putchar('\n'); } } /* Enough messing about */ #define IO_ERROR 2 #define BAD_INPUT 1 int main(int argc, char *argv[]) { struct cart *cart; /* Read input map and locate carts */ { FILE *input = fopen(argc > 1? argv[1]: "input.txt", "r"); int error = IO_ERROR; if (input) { error = BAD_INPUT; for (int row = 0; row < MAX_HEIGHT - 1; row++) { char *buf = playfield[row]; if (fgets(buf, MAX_WIDTH, input)) { if (buf[strlen(buf) - 1] != '\n') break; char *p = buf; while (p = strpbrk(p, cart_symbols)) { cart = &carts[num_carts++]; cart->x = p - buf; cart->y = row; cart->dir = strchr(cart_symbols, *p++) - cart_symbols; cart->turn = 0; cart->under = track_symbols[cart->dir]; cart->crashed = 0; } } else { error = 0; break; } } fclose(input); } if (error) return error; } if (0) show_carts(); if (0) show_playfield(); /* Update cart locations until crashes have removed all but one */ while (num_carts > 1) { for (cart = carts; cart < carts + num_carts; cart++) { const static int cos[] = {1, 0, -1, 0, 1}; const static int *sin = cos + 1; playfield[cart->y][cart->x] = cart->under; if (cart->crashed) continue; cart->x += cos[cart->dir]; cart->y += sin[cart->dir]; cart->under = playfield[cart->y][cart->x]; switch (cart->under) { case '+': cart->dir = (cart->dir + 1 - cart->turn) & 3; cart->turn = (cart->turn + 1) % 3; break; case '/': cart->dir ^= 1; break; case '\\': cart->dir ^= 3; break; case '|': if (!(cart->dir & 1)) goto crash; break; case '-': if (cart->dir & 1) goto crash; break; default: crash: for (struct cart *p = carts + num_carts - 1; p >= carts; p--) { if (p->x == cart->x && p->y == cart->y) { p->crashed = 1; playfield[p->y][p->x] = p->under; } } continue; } playfield[cart->y][cart->x] = cart_symbols[cart->dir]; } sort_carts(); if (0) show_carts(); while (num_carts && carts[num_carts - 1].crashed) num_carts--; if (0) show_carts(); if (0) show_playfield(); if (0) putchar('\n'); } if (0) show_playfield(); if (num_carts) printf("%d,%d\n", carts->x, carts->y); return 0; }