10 void debug(const char *fmt
, ...) {
12 if (getenv("DEBUG")) {
14 vfprintf(stderr
, fmt
, ap
);
22 static uint8_t map
[LIMIT
][LIMIT
];
25 uint8_t x
; /* coordinate on map to learn current direction */
27 char current
; /* what character to put back into map */
28 uint8_t turn
; /* next intersection: 0 left, 1 straight, 2 right, 3 dead */
31 static int sorter(const void *one
, const void *two
) {
32 const struct cart
*a
= one
;
33 const struct cart
*b
= two
;
34 if (a
->turn
!= 3 && b
->turn
== 3)
36 if (a
->turn
== 3 && b
->turn
!= 3)
49 static void dump(int tick
, int max
, int ncarts
) {
51 debug("\ntick %d:\n", tick
);
52 for (i
= 0; (getenv("DEBUG") ?: "1")[0] == '2' && i
< max
; i
++)
53 debug("%s\n", map
[i
]);
54 debug("%d carts at:\n", ncarts
);
55 for (i
= 0; i
< ncarts
; i
++) {
56 char p
= map
[carts
[i
].y
][carts
[i
].x
];
57 debug("%d: %d,%d %c on %c next %c turn %c\n", carts
[i
].id
, carts
[i
].x
,
58 carts
[i
].y
, map
[carts
[i
].y
][carts
[i
].x
], carts
[i
].current
,
59 map
[carts
[i
].y
- (p
== '^') + (p
== 'v')]
60 [carts
[i
].x
- (p
== '<') + (p
== '>')],
61 "lsrX"[carts
[i
].turn
]);
65 int move(int ticks
, struct cart
*cart
) {
66 uint8_t c
= map
[cart
->y
][cart
->x
];
68 map
[cart
->y
][cart
->x
] = cart
->current
;
72 p
= &map
[--cart
->y
][cart
->x
];
73 switch (cart
->current
= *p
) {
74 case '|': *p
= '^'; break;
75 case '\\': *p
= '<'; break;
76 case '/': *p
= '>'; break;
79 case 0: *p
= '<'; cart
->turn
= 1; break;
80 case 1: *p
= '^'; cart
->turn
= 2; break;
81 case 2: *p
= '>'; cart
->turn
= 0; break;
90 assert(cart
->y
< LIMIT
- 1);
91 p
= &map
[++cart
->y
][cart
->x
];
92 switch (cart
->current
= *p
) {
93 case '|': *p
= 'v'; break;
94 case '\\': *p
= '>'; break;
95 case '/': *p
= '<'; break;
98 case 0: *p
= '>'; cart
->turn
= 1; break;
99 case 1: *p
= 'v'; cart
->turn
= 2; break;
100 case 2: *p
= '<'; cart
->turn
= 0; break;
110 p
= &map
[cart
->y
][--cart
->x
];
111 switch (cart
->current
= *p
) {
112 case '-': *p
= '<'; break;
113 case '\\': *p
= '^'; break;
114 case '/': *p
= 'v'; break;
116 switch (cart
->turn
) {
117 case 0: *p
= 'v'; cart
->turn
= 1; break;
118 case 1: *p
= '<'; cart
->turn
= 2; break;
119 case 2: *p
= '^'; cart
->turn
= 0; break;
128 assert(cart
->x
< LIMIT
- 1);
129 p
= &map
[cart
->y
][++cart
->x
];
130 switch (cart
->current
= *p
) {
131 case '-': *p
= '>'; break;
132 case '\\': *p
= 'v'; break;
133 case '/': *p
= '^'; break;
135 switch (cart
->turn
) {
136 case 0: *p
= '^'; cart
->turn
= 1; break;
137 case 1: *p
= '>'; cart
->turn
= 2; break;
138 case 2: *p
= 'v'; cart
->turn
= 0; break;
151 printf("tick %d: collision at coordinate %d,%d\n", ticks
, cart
->x
, cart
->y
);
152 debug("removing %d\n", cart
->id
);
157 int main(int argc
, char **argv
) {
158 size_t len
= 0, count
= 0;
165 /* Part 1 - read in map */
166 if (argc
> 1 && !(stdin
= freopen(argv
[1], "r", stdin
))) {
171 while (getline(&line
, &len
, stdin
) >= 0) {
172 p
= strspn(line
, "^v<> /\\|-+") + line
;
173 if (*p
!= '\n' || p
- line
> LIMIT
) {
174 fprintf(stderr
, "recompile with larger limit\n");
177 p
= strcspn(line
, "^v<>\n") + line
;
179 carts
[ncarts
].x
= p
- line
;
180 carts
[ncarts
].y
= count
;
181 if (*p
== '^' || *p
== 'v')
182 carts
[ncarts
].current
= '|';
184 carts
[ncarts
].current
= '-';
185 carts
[ncarts
].id
= ncarts
;
188 p
= strcspn(p
, "^v<>\n") + p
;
190 memcpy(map
[count
++], line
, p
- line
);
191 if (count
== LIMIT
) {
192 fprintf(stderr
, "recompile with larger limit\n");
196 printf("read %zu lines, found %d carts\n", count
, ncarts
);
197 qsort(carts
, ncarts
, sizeof *carts
, sorter
);
198 dump(ticks
, count
, ncarts
);
200 fprintf(stderr
, "expecting odd number of carts\n");
204 /* Part 2 - iterate until last collision */
208 for (i
= 0; i
< ncarts
; i
++)
209 if (carts
[i
].turn
< 3 && move(ticks
, &carts
[i
]))
210 for (int j
= 0; j
< ncarts
; j
++)
211 if (i
!= j
&& carts
[j
].turn
< 3 &&
212 carts
[i
].x
== carts
[j
].x
&& carts
[i
].y
== carts
[j
].y
) {
213 debug("removing %d\n", carts
[j
].id
);
215 map
[carts
[i
].y
][carts
[i
].x
] = carts
[j
].current
;
218 qsort(carts
, ncarts
, sizeof *carts
, sorter
);
219 dump(ticks
, count
, n
);
221 printf("completed in %d ticks, last cart at %d,%d\n", ticks
, carts
->x
,