#include "lib.h" static ch input[] = { #embed "day6_input.txt" }; static ch test[] = { #embed "day6_test.txt" }; typedef struct { ch l[64]; } line; static_assert(sizeof(line) == 0x40); alignas(0x40) static struct { line padstart[4]; struct { num pad[3]; num prev_op_off, op_off, ledge_off, redge_off, rem; }; union { line l; struct { ch s[16]; num op, pad0, pad1, v; }; } b; union { line l; struct { ch s[16], pad0, sr[16], pad1; num v, vr; }; } a; line padend; } m; static_assert(offsetof(typeof(m),b) % 64 == 0); static_assert(sizeof(m.b) == 64); static_assert(sizeof(m.a) == 64); static_assert(offsetof(typeof(m),padend) % 64 == 0); static num do_part1(size_t file_len, ch file[file_len]) { ch *s = file; m = (typeof(m)){ }; s = memchr(s, '\n', file_len); const num stride = s - file; s = file; while (*s != '+' && *s != '*') s += stride; const num heightb = (s - file); const num height = (s - file) / stride; ch *const op = s; // constructing a pointer more than 1 past the end of an array // is UB, sadly, so we'll use offsets m.op_off = op - file; s = file; do { m.ledge_off = m.op_off - heightb; if (s[m.op_off] == '+') { m.a.v = 0; m.rem = height; m.b.op = '+' << 8; snprintd(m.a.v, 16, m.a.s); do { ch *t = s + m.ledge_off; while (*t < '0') t++; m.b.v = grabnum(t, NULL); snprintd(m.b.v, 16, m.b.s); m.a.v += m.b.v; snprintd(m.a.v, 16, m.a.s); m.ledge_off += stride; m.rem--; } while (m.rem); m.a.vr += m.a.v; snprintd(m.a.vr, 16, m.a.sr); } else if (s[m.op_off] == '*') { m.a.v = 1; m.rem = height; m.b.op = '*' << 8; snprintd(m.a.v, 16, m.a.s); do { ch *t = s + m.ledge_off; while (*t < '0') t++; m.b.v = grabnum(t, NULL); snprintd(m.b.v, 16, m.b.s); m.a.v *= m.b.v; snprintd(m.a.v, 16, m.a.s); m.ledge_off += stride; m.rem--; } while (m.rem); m.a.vr += m.a.v; snprintd(m.a.vr, 16, m.a.sr); } m.op_off++; while (m.op_off < file_len) { if (s[m.op_off] == '+' || s[m.op_off] == '*') break; m.op_off++; } } while (m.op_off < file_len); return m.a.vr; } static num do_part2(size_t file_len, unsigned char file[file_len]) { ch *s = file; m = (typeof(m)){ }; s = memchr(s, '\n', file_len); const num stride = s - file; s = file; while (*s != '+' && *s != '*') s += stride; const num heightb = (s - file); const num height = (s - file) / stride; ch *const op = s; // constructing a pointer more than 1 past the end of an array // is UB, sadly, so we'll use offsets const num fop_off = op - file; m.prev_op_off = fop_off + stride - 1; s = file; do { // we don't need to do these in the same order as the example // because both these operations are commutative. // but you know what? we can anyway. for fun. and pretty output { num op_off = m.prev_op_off - 1; while (s[op_off] != '+' && s[op_off] != '*' && s[op_off] != '\n') op_off--; m.op_off = op_off; } m.ledge_off = m.op_off - heightb; m.redge_off = (s[m.prev_op_off] == '\n' ? -1 : -2) + m.prev_op_off - heightb; if (s[m.op_off] == '+') { m.a.v = 0; m.rem = m.redge_off - m.ledge_off + 1; const num frem = m.rem; m.b.op = '+' << 8; snprintd(m.a.v, 16, m.a.s); do { m.b.v = 0; ch *t = s + m.redge_off; for (num i = height; i; i--,t+=stride) { if (*t >= '0') { m.b.v *= 10; m.b.v += *t - '0'; } } snprintd(m.b.v, 16, m.b.s); m.a.v += m.b.v; snprintd(m.a.v, 16, m.a.s); m.redge_off--; m.rem--; } while (m.rem); m.a.vr += m.a.v; snprintd(m.a.vr, 16, m.a.sr); } else if (s[m.op_off] == '*') { m.a.v = 1; m.rem = m.redge_off - m.ledge_off + 1; const num frem = m.rem; m.b.op = '*' << 8; snprintd(m.a.v, 16, m.a.s); do { m.b.v = 0; ch *t = s + m.redge_off; for (num i = height; i; i--,t+=stride) { if (*t >= '0') { m.b.v *= 10; m.b.v += *t - '0'; } } snprintd(m.b.v, 16, m.b.s); m.a.v *= m.b.v; snprintd(m.a.v, 16, m.a.s); m.redge_off--; m.rem--; } while (m.rem); m.a.vr += m.a.v; snprintd(m.a.vr, 16, m.a.sr); } m.prev_op_off = m.op_off; } while (m.prev_op_off != fop_off); return m.a.vr; } #define RUN_TEST1 1 #define RUN_PART1 1 #define RUN_TEST2 1 #define RUN_PART2 1 #define TEST1_EXPECT 4277556 #define TEST2_EXPECT 3263827 void run() { #if RUN_TEST1 print("PART 1 TEST: "); if (num v = do_part1(countof(test), test); v != TEST1_EXPECT) { print("FAILED (got "); printd(v); print(", expected " xstr(TEST1_EXPECT) ")\n"); } else { print("PASSED\n"); } #endif #if RUN_PART1 print("PART 1 RESULT: "); printd(do_part1(countof(input), input)); print("\n"); #endif #if RUN_TEST2 print("PART 2 TEST: "); if (num v = do_part2(countof(test), test); v != TEST2_EXPECT) { print("FAILED (got "); printd(v); print(", expected " xstr(TEST2_EXPECT) ")\n"); } else { print("PASSED\n"); } #endif #if RUN_PART2 print("PART 2 RESULT: "); printd(do_part2(countof(input), input)); print("\n"); #endif exit_group(0); }