somewhat optimized day 2. for fun
This commit is contained in:
6
day2.c
6
day2.c
@@ -249,10 +249,10 @@ no_len_change:
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define RUN_TEST1 1
|
#define RUN_TEST1 0
|
||||||
#define RUN_PART1 1
|
#define RUN_PART1 0
|
||||||
#define RUN_TEST2 0
|
#define RUN_TEST2 0
|
||||||
#define RUN_PART2 0
|
#define RUN_PART2 1
|
||||||
|
|
||||||
#define TEST1_EXPECT 0x1227775554l
|
#define TEST1_EXPECT 0x1227775554l
|
||||||
#define TEST2_EXPECT 0x4174379265l
|
#define TEST2_EXPECT 0x4174379265l
|
||||||
|
|||||||
257
day2opt.c
Normal file
257
day2opt.c
Normal file
@@ -0,0 +1,257 @@
|
|||||||
|
#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);
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user