advent-of-code-2024/day-13/main.c

95 lines
2.4 KiB
C

#include "aoc.h"
#include <limits.h>
#include <ctype.h>
typedef struct Vec2i {
i64 x;
i64 y;
} Vec2i;
static Vec2i
parse_numbers(str line, Arena *arena) {
bool x_set = false;
Vec2i result = {0};
for (isize i = 0; i < line.len; i++) {
if (isdigit(line.data[i])) {
isize end = i + 1;
while (end < line.len && isdigit(line.data[end])) {
end++;
}
str num_str = str_sub(line, i, end);
if (!x_set) {
result.x = (i32) parse_i64(num_str, *arena);
x_set = true;
}
else {
result.y = (i32) parse_i64(num_str, *arena);
return result;
}
i = end;
}
}
NOT_REACHABLE();
}
static bool
solve(Vec2i a, Vec2i b, Vec2i p, Vec2i *solution) {
i64 det = a.x * b.y - a.y * b.x;
ASSERT(det != 0);
i64 numerator_a = p.x * b.y - p.y * b.x;
i64 numerator_b = p.y * a.x - p.x * a.y;
bool solved = false;
if ((numerator_a % det == 0) && (numerator_b % det == 0)) {
i64 n_a = numerator_a / det;
i64 n_b = numerator_b / det;
if (n_a >= 0 && n_b >= 0) {
solution->x = n_a;
solution->y = n_b;
solved = true;
}
}
else {
// no integer solution
}
return solved;
}
int main(int argc, char **argv) {
Arena *arena = make_arena(Megabytes(1));
str input = read_file(arena, argv[1]);
str line;
i64 part_1 = 0;
i64 part_2 = 0;
while (input.len > 0) {
str a_line = str_next_token(&input, STR("\n"));
str b_line = str_next_token(&input, STR("\n"));
str prize_line = str_next_token(&input, STR("\n"));
str empty_line = str_next_token(&input, STR("\n"));
ASSERT(str_trim(empty_line).len == 0);
Vec2i a = parse_numbers(a_line, arena);
Vec2i b = parse_numbers(b_line, arena);
Vec2i p = parse_numbers(prize_line, arena);
Vec2i p_ = { p.x + 10000000000000ull, p.y + 10000000000000ull };
#if 0
printf("a: %ld %ld\n", a.x, a.y);
printf("b: %ld %ld\n", b.x, b.y);
printf("p: %ld %ld\n", p.x, p.y);
printf("\n");
#endif
Vec2i n;
if (solve(a, b, p, &n)) {
part_1 += n.x * 3 + n.y;
}
if (solve(a, b, p_, &n)) {
part_2 += n.x * 3 + n.y;
}
}
printf("%ld\n", part_1);
printf("%ld\n", part_2);
}