#include "lib.h" #define DBG 0 static alignas(0x40) unsigned char input[] = { #embed "day2_input.txt" }; struct id { size_t len; bcdint v; }; static bcdint next_palindrome_len2(bcdint in) { bcdint low = in & 0xF; bcdint high = in >> 4; bcdint higher = high + 1; bcdint high_pd = 0x11 * high; bcdint higher_pd = 0x11 * higher; return low > high ? higher_pd : high_pd; } static bcdint next_palindrome_len3(bcdint in) { bcdint nib0 = in & 0xF; bcdint nib1 = (in >> 4) & 0xF; bcdint high = in >> 8; bcdint higher = high + 1; bcdint high_pd = 0x111 * high; bcdint higher_pd = 0x111 * higher; if (nib1 < high) return high_pd; return nib0 > high ? higher_pd : high_pd; } static bcdint next_palindrome_len4(bcdint in) { bcdint nib0 = in & 0xF; bcdint nib1 = (in >> 4) & 0xF; bcdint nib2 = (in >> 8) & 0xF; bcdint nib3 = in >> 12; bcdint nib3er = nib3 + 1; bcdint nib3_pd = 0x1111 * nib3; bcdint nib3er_pd = 0x1111 * nib3er; bcdint nib10 = in & 0xFF; bcdint nib32 = in >> 8; bcdint nib32er = bcdadd(nib32, 1); bcdint nib32_pd = 0x0101 * nib32; bcdint nib32er_pd = 0x0101 * nib32er; bcdint r = nib3er_pd; if (nib3_pd > in) r = nib3_pd; if (nib32er_pd > in) r = nib32er_pd; if (nib32_pd > in) r = nib32_pd; return r; } static bcdint next_palindrome_len6(bcdint in) { bcdint nib0 = in & 0xF; bcdint nib1 = (in >> 4) & 0xF; bcdint nib2 = (in >> 8) & 0xF; bcdint nib3 = (in >> 12) & 0xF; bcdint nib4 = (in >> 16) & 0xF; bcdint nib5 = in >> 20; bcdint nib5er = nib5 + 1; bcdint nib5_pd = 0x111111 * nib5; bcdint nib5er_pd = 0x111111 * nib5er; bcdint nib10 = in & 0xFF; bcdint nib32 = (in >> 8) & 0xFF; bcdint nib54 = in >> 16; bcdint nib54er = bcdadd(nib54, 1); bcdint nib54_pd = 0x010101 * nib54; bcdint nib54er_pd = 0x010101 * nib54er; bcdint nib210 = in & 0xFFF; bcdint nib543 = in >> 12; bcdint nib543er = bcdadd(nib543, 1); bcdint nib543_pd = 0x001001 * nib543; bcdint nib543er_pd = 0x001001 * nib543er; bcdint r = nib5er_pd; if (nib5_pd > in) r = MIN(r,nib5_pd); if (nib54er_pd > in) r = MIN(r,nib54er_pd); if (nib54_pd > in) r = MIN(r,nib54_pd); if (nib543er_pd > in) r = MIN(r,nib543er_pd); if (nib543_pd > in) r = MIN(r,nib543_pd); return r; } static bcdint next_palindrome_len8(bcdint in) { bcdint nib0 = in & 0xF; bcdint nib1 = (in >> 4) & 0xF; bcdint nib2 = (in >> 8) & 0xF; bcdint nib3 = (in >> 12) & 0xF; bcdint nib4 = (in >> 16) & 0xF; bcdint nib5 = (in >> 20) & 0xF; bcdint nib6 = (in >> 24) & 0xF; bcdint nib7 = in >> 28; bcdint nib7er = nib7 + 1; bcdint nib7_pd = 0x11111111 * nib7; bcdint nib7er_pd = 0x11111111 * nib7er; bcdint nib10 = in & 0xFF; bcdint nib32 = (in >> 8) & 0xFF; bcdint nib54 = (in >> 16) & 0xFF; bcdint nib76 = in >> 24; bcdint nib76er = bcdadd(nib76, 1); bcdint nib76_pd = 0x01010101 * nib76; bcdint nib76er_pd = 0x01010101 * nib76er; bcdint nib3210 = in & 0xFFFF; bcdint nib7654 = in >> 16; bcdint nib7654er = bcdadd(nib7654, 1); bcdint nib7654_pd = 0x00010001 * nib7654; bcdint nib7654er_pd = 0x00010001 * nib7654er; bcdint r = nib7er_pd; if (nib7_pd > in) r = MIN(r,nib7_pd); if (nib76er_pd > in) r = MIN(r,nib76er_pd); if (nib76_pd > in) r = MIN(r,nib76_pd); if (nib7654er_pd > in) r = MIN(r,nib7654er_pd); if (nib7654_pd > in) r = MIN(r,nib7654_pd); return r; } static bcdint next_palindrome_part2(struct id s) { if (s.len == 2) return next_palindrome_len2(s.v); else if (s.len == 3) return next_palindrome_len3(s.v); else if (s.len == 4) return next_palindrome_len4(s.v); else if (s.len == 6) return next_palindrome_len6(s.v); else if (s.len == 8) return next_palindrome_len8(s.v); unsigned len = s.len; bcdint in = s.v; bcdint best = -1; for (unsigned i = 2; i <= len; i++) { if (len % i == 0) { unsigned high_shift = (len / i) * 4; bcdint high = in >> (high_shift * (i - 1)); for (int j = i - 2; j >= 0; j--) { bcdint low = (in >> (high_shift * (j))) & ((1 << high_shift) - 1); if (low < high) { break; } else if (low > high) { high = bcdadd(high, 1); break; } } bcdint next = 0; for (unsigned j = 0; j < i; j++) { next |= high << (high_shift * j); } if (next < best) { best = next; } } } return best; } static bcdint do_part2(size_t file_len, unsigned char file[file_len]) { unsigned char *src = file; bcdint result = 0; alignas(0x40) struct id ranges[128]; size_t range_count = 0; do { unsigned char *tmp; bcdint rs = grabbcd(src, &tmp); ranges[range_count * 2 + 0] = (struct id) { .len = tmp - src, .v = rs }; src = tmp + 1; bcdint re = grabbcd(src, &tmp); ranges[range_count * 2 + 1] = (struct id) { .v = re }; src = tmp + 1; range_count++; } while (src != &file[file_len]); do { range_count--; struct id next = ranges[range_count * 2 + 0]; bcdint re = ranges[range_count * 2 + 1].v; do { if (next.len == 1) { next = (struct id) { .len = 2, .v = 0x11 }; } else { next.v = next_palindrome_part2(next); } if (next.v <= re) { result = bcdadd(result, next.v); } bcdint tmp = bcdadd(next.v, 1); for (bcdint chk = next.v; chk > 0; chk >>= 4) { if ((chk & 0xF) != 9) goto no_len_change; } next.len++; no_len_change: next.v = tmp; } while (next.v <= re); } while (range_count); return result; } void run() { print("PART 2 RESULT: "); printh(do_part2(countof(input), input)); print("\n"); exit_group(0); }