125 lines
2.8 KiB
C
125 lines
2.8 KiB
C
#include <stdint.h>
|
|
|
|
#include "linear_algebra.h"
|
|
#include "parse.h"
|
|
|
|
struct button {
|
|
int x;
|
|
int y;
|
|
};
|
|
|
|
struct prize {
|
|
int x;
|
|
int y;
|
|
};
|
|
|
|
struct claw_machine {
|
|
struct {
|
|
struct button a;
|
|
struct button b;
|
|
} button;
|
|
struct prize prize;
|
|
};
|
|
|
|
static const char * parse_button(const char * input, char c,
|
|
int * x, int * y)
|
|
{
|
|
input = parse_match(input, "Button ");
|
|
input = parse_skip(input, c);
|
|
input = parse_match(input, ": X+");
|
|
input = parse_base10(input, x);
|
|
input = parse_match(input, ", Y+");
|
|
input = parse_base10(input, y);
|
|
input = parse_skip(input, '\n');
|
|
return input;
|
|
}
|
|
|
|
static const char * parse_prize(const char * input,
|
|
int * x, int * y)
|
|
{
|
|
input = parse_match(input, "Prize: X=");
|
|
input = parse_base10(input, x);
|
|
input = parse_match(input, ", Y=");
|
|
input = parse_base10(input, y);
|
|
input = parse_skip(input, '\n');
|
|
return input;
|
|
}
|
|
|
|
static const char * parse_claw_machine(const char * input,
|
|
struct claw_machine * cm)
|
|
{
|
|
input = parse_button(input, 'A', &cm->button.a.x, &cm->button.a.y);
|
|
input = parse_button(input, 'B', &cm->button.b.x, &cm->button.b.y);
|
|
input = parse_prize(input, &cm->prize.x, &cm->prize.y);
|
|
return input;
|
|
}
|
|
|
|
static bool is_integral(double x)
|
|
{
|
|
int64_t ix = x;
|
|
double dx = ix;
|
|
double diff = dx - x;
|
|
return (diff < 0.00000001) && (diff > -0.00000001);
|
|
}
|
|
|
|
int64_t _2024_day13_part1(const char * input, int length)
|
|
{
|
|
const char * end = input + length;
|
|
|
|
int cost = 0;
|
|
|
|
while (input < end) {
|
|
struct claw_machine cm;
|
|
input = parse_claw_machine(input, &cm);
|
|
|
|
double ax = cm.button.a.x;
|
|
double ay = cm.button.a.y;
|
|
double bx = cm.button.b.x;
|
|
double by = cm.button.b.y;
|
|
double x = cm.prize.x;
|
|
double y = cm.prize.y;
|
|
|
|
struct double2 r = cramers_rule_2x2(ax, bx, x,
|
|
ay, by, y);
|
|
if (is_integral(r.x) && is_integral(r.y)) {
|
|
int a = (int)r.x;
|
|
int b = (int)r.y;
|
|
cost += a * 3 + b;
|
|
}
|
|
}
|
|
return cost;
|
|
}
|
|
|
|
int64_t _2024_day13_part2(const char * input, int length)
|
|
{
|
|
const char * end = input + length;
|
|
|
|
int64_t cost = 0;
|
|
|
|
while (input < end) {
|
|
struct claw_machine cm;
|
|
input = parse_claw_machine(input, &cm);
|
|
|
|
double ax = cm.button.a.x;
|
|
double ay = cm.button.a.y;
|
|
double bx = cm.button.b.x;
|
|
double by = cm.button.b.y;
|
|
double x = cm.prize.x;
|
|
double y = cm.prize.y;
|
|
x += 10000000000000;
|
|
y += 10000000000000;
|
|
|
|
struct double2 r = cramers_rule_2x2(ax, bx, x,
|
|
ay, by, y);
|
|
if (r.x == infinity || r.y == infinity) {
|
|
continue;
|
|
}
|
|
if (is_integral(r.x) && is_integral(r.y)) {
|
|
int64_t a = (int64_t)(r.x);
|
|
int64_t b = (int64_t)(r.y);
|
|
cost += a * 3 + b;
|
|
}
|
|
}
|
|
return cost;
|
|
}
|