aoc

My solutions for the Advent of Code
git clone https://git.tronto.net/aoc
Download | Log | Files | Refs | README

8b.c (1941B)


      1 /*
      2 I hate this stupid problem. There are a bunch of unwritten properties
      3 of the paths that make the problem very simple:
      4 
      5 - Different ghosts' paths do not end up in the same Z-node.
      6 - Each ghost has exactly one Z-node in its path.
      7 - Each ghost meets a Z-node exactly once before entering a loop.
      8 - If a ghost encounters a Z-node after X steps, it will encounter it exactly
      9   every X steps; preperiods just end up aligning nicely.
     10 
     11 In practice, everything just works out so that the lcm of the periods
     12 is the solution, which is very much not the case for a general input.
     13 This code computes the periods of the paths of the different ghosts. Then
     14 you can figure out the solution with a pocket calculator, or by hand.
     15 */
     16 
     17 #include <stdio.h>
     18 #include <string.h>
     19 
     20 #define N 1000
     21 
     22 typedef struct { char last; int next[2]; } node_t;
     23 
     24 int v[N*N];
     25 
     26 int ind(char s[3], char m[][3], int n) {
     27 	for (int j = 0; j < n; j++)
     28 		if (s[0] == m[j][0] && s[1] == m[j][1] && s[2] == m[j][2])
     29 			return j;
     30 	return -1;
     31 }
     32 
     33 int findperiod(int i, node_t *nodes, char *dir, int n, int k) {
     34 	memset(v, 0, sizeof(int) * N*N);
     35 	for (int j = i, d = 0, l = 1, state = -1; ; d = (d+1)%k) {
     36 		j = nodes[j].next[dir[d] == 'R'];
     37 		state = j*k+d;
     38 		if (v[state]) return l - v[state];
     39 		else v[state] = l++;
     40 	}
     41 	return -1;
     42 }
     43 
     44 int main() {
     45 	node_t nodes[N];
     46 	char *buf, dir[N], line[N], name[N][3], lstr[N][3], rstr[N][3];
     47 	int k, n;
     48 
     49 	k = strlen(fgets(dir, N, stdin)) - 1;
     50 	fgets(line, N, stdin);
     51 	for (n = 0; (buf = fgets(line, N, stdin)) != NULL; n++) {
     52 		memcpy(name[n], buf, 3);
     53 		nodes[n].last = name[n][2];
     54 		while (*buf != '(') buf++;
     55 		memcpy(lstr[n], buf+1, 3);
     56 		while (*buf != ' ') buf++;
     57 		memcpy(rstr[n], buf+1, 3);
     58 	}
     59 
     60 	for (int i = 0; i < n; i++) {
     61 		nodes[i].next[0] = ind(lstr[i], name, n);
     62 		nodes[i].next[1] = ind(rstr[i], name, n);
     63 	}
     64 
     65 	for (int i = 0; i < n; i++)
     66 		if (nodes[i].last == 'A')
     67 			printf("%d\n", findperiod(i, nodes, dir, n, k));
     68 
     69 	return 0;
     70 }