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;
|
||||
}
|
||||
|
||||
#define RUN_TEST1 1
|
||||
#define RUN_PART1 1
|
||||
#define RUN_TEST1 0
|
||||
#define RUN_PART1 0
|
||||
#define RUN_TEST2 0
|
||||
#define RUN_PART2 0
|
||||
#define RUN_PART2 1
|
||||
|
||||
#define TEST1_EXPECT 0x1227775554l
|
||||
#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