#include "lib.h" #define DBG 0 static ch input[] = { #embed "day6_input.txt" }; static ch test[] = { #embed "day6_test.txt" }; static num do_part1(size_t file_len, ch file[file_len]) { ch *s = file; num result = 0; s = memchr(s, '\n', file_len); num stride = s - file; s = file; while (*s != '+' && *s != '*') s += stride; num heightb = (s - file); num height = (s - file) / stride; ch *op = s; // 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; s = file; do { num ledge_off = op_off - heightb; if (s[op_off] == '+') { num a = 0; num rem = height; do { ch *t = s + ledge_off; while (*t < '0') t++; num b = grabnum(t, NULL); a += b; ledge_off += stride; rem--; } while (rem); result += a; } else if (s[op_off] == '*') { num a = 1; num rem = height; do { ch *t = s + ledge_off; while (*t < '0') t++; num b = grabnum(t, NULL); #if DBG if (rem < height) { print("\t*\t"); } printd(b); #endif a *= b; ledge_off += stride; rem--; } while (rem); result += a; #if DBG print("\t= "); printd(a); print("\n"); #endif } #if DBG else { print("INVALID OP\n"); exit_group(-1); } #endif op_off++; while (op_off < file_len) { if (s[op_off] == '+' || s[op_off] == '*') break; op_off++; } } while (op_off < file_len); return result; } static num do_part2(size_t file_len, unsigned char file[file_len]) { ch *s = file; num result = 0; #if DBG print("\n"); #endif s = memchr(s, '\n', file_len); num stride = s - file; s = file; while (*s != '+' && *s != '*') s += stride; num heightb = (s - file); 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 fop_off = op - file; num 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 = prev_op_off - 1; while (s[op_off] != '+' && s[op_off] != '*' && s[op_off] != '\n') op_off--; num ledge_off = op_off - heightb; num redge_off = (s[prev_op_off] == '\n' ? -1 : -2) + prev_op_off - heightb; if (s[op_off] == '+') { num a = 0; num rem = redge_off - ledge_off + 1; num frem = rem; do { num b = 0; ch *t = s + redge_off; for (num i = height; i; i--,t+=stride) { if (*t >= '0') { b *= 10; b += *t - '0'; } } #if DBG if (rem < frem) { print("\t+\t"); } printd(b); #endif a += b; redge_off--; rem--; } while (rem); result += a; #if DBG print("\t=\t"); printd(a); print("\n"); #endif } else if (s[op_off] == '*') { num a = 1; num rem = redge_off - ledge_off + 1; num frem = rem; do { num b = 0; ch *t = s + redge_off; for (num i = height; i; i--,t+=stride) { if (*t >= '0') { b *= 10; b += *t - '0'; } } #if DBG if (rem < frem) { print("\t*\t"); } printd(b); #endif a *= b; redge_off--; rem--; } while (rem); result += a; #if DBG print("\t=\t"); printd(a); print("\n"); #endif } #if DBG else { print("INVALID OP\n"); exit_group(-1); } #endif prev_op_off = op_off; } while (prev_op_off != fop_off); return result; } #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); }