diff --git a/day6.c b/day6.c index 7f9edd2..812c5c2 100644 --- a/day6.c +++ b/day6.c @@ -1,7 +1,6 @@ #include "lib.h" #define DBG 0 -#define PRETTY 1 static ch input[] = { @@ -13,42 +12,11 @@ ch test[] = { #embed "day6_test.txt" }; -#if PRETTY -struct line { - union { - ch l[24]; - struct { - ch vs[16]; - ch pad[4]; - num v; - }; - }; -} __attribute__((aligned(0x40))); -static_assert(alignof(struct line) == 0x40); -#endif - -#if PRETTY -alignas(0x40) static -struct line linemem[6]; -struct line *const op_line = &linemem[1]; -struct line *const a_line = &linemem[2]; -struct line *const b_line = &linemem[3]; -struct line *const result_line = &linemem[4]; -#endif - static num do_part1(size_t file_len, ch file[file_len]) { ch *s = file; num result = 0; -#if PRETTY - memset(linemem, 0, sizeof(linemem)); - snprintd(result, 16, result_line->vs); -#endif -#if DBG - print("\n"); -#endif - s = memchr(s, '\n', file_len); num stride = s - file; @@ -58,11 +26,6 @@ num do_part1(size_t file_len, ch file[file_len]) { num height = (s - file) / stride; ch *op = s; -#if DBG - print("STRIDE\t"); printd(stride); print("\n"); - print("HEIGHT\t"); printd(height); print("\n"); -#endif - // constructing a pointer more than 1 past the end of an array // is UB, sadly, so we'll use offsets num op_off = op - file; @@ -72,74 +35,31 @@ num do_part1(size_t file_len, ch file[file_len]) { if (s[op_off] == '+') { num a = 0; num rem = height; -#if PRETTY - op_line->vs[15] = '+'; - a_line->v = a; - snprintd(a, 16, a_line->vs); - *b_line = (struct line){ }; -#endif do { ch *t = s + ledge_off; while (*t < '0') t++; num b = grabnum(t, NULL); -#if PRETTY - b_line->v = b; - snprintd(b, 16, b_line->vs); -#endif -#if DBG - if (rem < height) { print("\t+\t"); } - printd(b); -#endif a += b; -#if PRETTY - a_line->v = a; - snprintd(a, 16, a_line->vs); -#endif ledge_off += stride; rem--; } while (rem); result += a; -#if PRETTY - result_line->v = result; - snprintd(result, 16, result_line->vs); -#endif -#if DBG - print("\t= "); printd(a); print("\n"); -#endif } else if (s[op_off] == '*') { num a = 1; -#if PRETTY - op_line->vs[15] = '*'; - a_line->v = a; - snprintd(a, 16, a_line->vs); - *b_line = (struct line){ }; -#endif num rem = height; do { ch *t = s + ledge_off; while (*t < '0') t++; num b = grabnum(t, NULL); -#if PRETTY - b_line->v = b; - snprintd(b, 16, b_line->vs); -#endif #if DBG if (rem < height) { print("\t*\t"); } printd(b); #endif a *= b; -#if PRETTY - a_line->v = a; - snprintd(a, 16, a_line->vs); -#endif ledge_off += stride; rem--; } while (rem); result += a; -#if PRETTY - result_line->v = result; - snprintd(result, 16, result_line->vs); -#endif #if DBG print("\t= "); printd(a); print("\n"); #endif @@ -158,12 +78,6 @@ num do_part1(size_t file_len, ch file[file_len]) { } } while (op_off < file_len); -#if PRETTY - *op_line = (struct line){ }; - *a_line = (struct line){ }; - *b_line = (struct line){ }; -#endif - return result; } @@ -172,10 +86,6 @@ num do_part2(size_t file_len, unsigned char file[file_len]) { ch *s = file; num result = 0; -#if PRETTY - memset(linemem, 0, sizeof(linemem)); - snprintd(result, 16, result_line->vs); -#endif #if DBG print("\n"); #endif @@ -212,12 +122,6 @@ num do_part2(size_t file_len, unsigned char file[file_len]) { num a = 0; num rem = redge_off - ledge_off + 1; num frem = rem; -#if PRETTY - op_line->vs[15] = '+'; - a_line->v = a; - snprintd(a, 16, a_line->vs); - *b_line = (struct line){ }; -#endif do { num b = 0; ch *t = s + redge_off; @@ -227,10 +131,6 @@ num do_part2(size_t file_len, unsigned char file[file_len]) { b += *t - '0'; } } -#if PRETTY - b_line->v = b; - snprintd(b, 16, b_line->vs); -#endif #if DBG if (rem < frem) { print("\t+\t"); } printd(b); @@ -240,10 +140,6 @@ num do_part2(size_t file_len, unsigned char file[file_len]) { rem--; } while (rem); result += a; -#if PRETTY - result_line->v = result; - snprintd(result, 16, result_line->vs); -#endif #if DBG print("\t=\t"); printd(a); print("\n"); #endif @@ -251,12 +147,6 @@ num do_part2(size_t file_len, unsigned char file[file_len]) { num a = 1; num rem = redge_off - ledge_off + 1; num frem = rem; -#if PRETTY - op_line->vs[15] = '*'; - a_line->v = a; - snprintd(a, 16, a_line->vs); - *b_line = (struct line){ }; -#endif do { num b = 0; ch *t = s + redge_off; @@ -266,10 +156,6 @@ num do_part2(size_t file_len, unsigned char file[file_len]) { b += *t - '0'; } } -#if PRETTY - b_line->v = b; - snprintd(b, 16, b_line->vs); -#endif #if DBG if (rem < frem) { print("\t*\t"); } printd(b); @@ -279,10 +165,6 @@ num do_part2(size_t file_len, unsigned char file[file_len]) { rem--; } while (rem); result += a; -#if PRETTY - result_line->v = result; - snprintd(result, 16, result_line->vs); -#endif #if DBG print("\t=\t"); printd(a); print("\n"); #endif @@ -296,17 +178,11 @@ num do_part2(size_t file_len, unsigned char file[file_len]) { prev_op_off = op_off; } while (prev_op_off != fop_off); -#if PRETTY - *op_line = (struct line){ }; - *a_line = (struct line){ }; - *b_line = (struct line){ }; -#endif - return result; } -#define RUN_TEST1 0 -#define RUN_PART1 0 +#define RUN_TEST1 1 +#define RUN_PART1 1 #define RUN_TEST2 1 #define RUN_PART2 1 diff --git a/day6pretty.c b/day6pretty.c new file mode 100644 index 0000000..4aec0fe --- /dev/null +++ b/day6pretty.c @@ -0,0 +1,228 @@ +#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); +}