#include "lib.h" #include #define DBG 0 #define PRETTY 1 static unsigned char input[] = { #embed "day5_input.txt" }; static unsigned char test[] = { #embed "day5_test.txt" }; #if PRETTY struct line { union { unsigned char l[64]; struct { unsigned char s[16]; unsigned char pad0[4]; unsigned char e[16]; unsigned char pad1[4]; num sv; num ev; }; }; }; static_assert(sizeof(struct line) == 0x40); #else struct line { num sv; num ev; }; #endif alignas(0x40) static struct line ranges[256]; static int linecmp(const void *av, const void *bv) { const struct line *a = av; const struct line *b = bv; if (a->sv < b->sv) return -1; else if (a->sv > b->sv) return 1; else return 0; } static unsigned long do_part1(size_t file_len, unsigned char file[file_len]) { unsigned char *s = file; unsigned long result = 0; memset(ranges, 0, sizeof(ranges)); #if DBG print("\n"); #endif struct line *d = ranges; do { unsigned char *tmp; d->sv = grabbcd(s, &tmp); #if PRETTY memcpy(d->s, s, tmp - s); #endif s = tmp; s++; d->ev = grabbcd(s, &tmp); #if PRETTY memcpy(d->e, s, tmp - s); #endif s = tmp; s++; d++; } while (*s != '\n'); #if PRETTY size_t range_cnt = d - ranges; qsort(ranges, range_cnt, sizeof(*ranges), linecmp); #endif d->sv = 0; s++; do { bcdint id = grabbcd(s, &s); for (d = ranges; d->sv; d++) { bcdint ds = d->sv; bcdint de = d->ev; if (id >= ds && id <= de) { result++; goto next_id; } } next_id: s++; } while (s != &file[file_len]); return result; } static unsigned long do_part2(size_t file_len, unsigned char file[file_len]) { unsigned char *s = file; unsigned long result = 0; memset(ranges, 0, sizeof(ranges)); #if DBG print("\n"); #endif struct line *d = ranges; do { unsigned char *tmp; d->sv = grabbcd(s, &tmp); #if PRETTY snprinth(d->sv, sizeof(d->s), d->s); #endif s = tmp; s++; d->ev = grabbcd(s, &tmp); #if PRETTY snprinth(d->ev, sizeof(d->e), d->e); #endif s = tmp; s++; d++; } while (*s != '\n'); #if PRETTY size_t range_cnt = d - ranges; qsort(ranges, range_cnt, sizeof(*ranges), linecmp); #endif d->sv = 0; outer: for (struct line *di = ranges; di->sv; di++) { bcdint dis = di->sv; bcdint die = di->ev; if (dis == -1) continue; for (struct line *dj = di+1; dj->sv; dj++) { bcdint djs = dj->sv; bcdint dje = dj->ev; if (djs == -1) continue; if (djs <= die && djs >= dis) { djs = bcdadd(die, 1); } if (dje >= dis && dje <= die) { dje = bcdsub(dis, 1); } if (djs == dj->sv && dje == dj->ev) continue; if (dje < djs) { #if DBG print("FOR: "); printd(dis); print(" "); printd(die); print("\n"); print(" "); printd(dj->sv); print(" "); printd(dj->ev); print("\n"); print(" -> "); printd(djs); print(" "); printd(dje); print(" BAD\n"); #endif dj->sv = -1; dj->ev = -1; #if PRETTY snprinth(dj->sv, sizeof(dj->s), dj->s); snprinth(dj->ev, sizeof(dj->e), dj->e); #endif } else { #if DBG print("FOR: "); printd(dis); print(" "); printd(die); print("\n"); print(" "); printd(dj->sv); print(" "); printd(dj->ev); print("\n"); print(" -> "); printd(djs); print(" "); printd(dje); print("\n"); #endif dj->sv = djs; dj->ev = dje; #if PRETTY snprinth(dj->sv, sizeof(dj->s), dj->s); snprinth(dj->ev, sizeof(dj->e), dj->e); #endif } } } for (struct line *di = ranges; di->sv; di++) { if (di->sv == -1) continue; unsigned long dis = bcdtonum(di->sv); unsigned long die = bcdtonum(di->ev); result += die - dis + 1; } return result; } #define RUN_TEST1 1 #define RUN_PART1 1 #define RUN_TEST2 1 #define RUN_PART2 1 #define TEST1_EXPECT 3 #define TEST2_EXPECT 14 void run() { #if RUN_TEST1 print("PART 1 TEST: "); if (unsigned long 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 (unsigned long 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); }