Files
aoc2025/day5.c
2025-12-05 15:19:05 -06:00

241 lines
5.2 KiB
C

#include "lib.h"
#include <stdlib.h>
#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);
}