diff --git a/c/2024/13/claw_contraption.c b/c/2024/13/claw_contraption.c new file mode 100644 index 0000000..7c7a164 --- /dev/null +++ b/c/2024/13/claw_contraption.c @@ -0,0 +1,108 @@ +#include +#include +#include +#include + +#include "../../lib/aoc.h" + +typedef struct Ratio { + long long num; + long long denom; +} Ratio; + +typedef struct Line { + Ratio slope; + Ratio offset; +} Line; + +Ratio ratio_subtract(Ratio r1, Ratio r2) { + Ratio r3; + r3.num= r1.num * r2.denom - r2.num * r1.denom; + r3.denom= r1.denom* r2.denom; + return r3; +} + +Ratio ratio_divide(Ratio r1, Ratio r2) { + Ratio r3; + r3.num = r1.num * r2.denom; + r3.denom = r1.denom * r2.num; + return r3; +} + +bool proper(Ratio r) { + return r.num % r.denom == 0; +} + +Ratio intersect_x(Line l1, Line l2) { + Ratio left_side = ratio_subtract(l1.slope, l2.slope); + Ratio right_side = ratio_subtract(l2.offset, l1.offset); + Ratio divided = ratio_divide(right_side, left_side); + return divided; +} + +int li_cost(int ax, int ay, int bx, int by, int px, int py) { + Line b_line; + b_line.slope.num = by; + b_line.slope.denom = bx; + b_line.offset.num = 0; + b_line.offset.denom = 1; + + Line a_line; + a_line.slope.num = ay; + a_line.slope.denom = ax; + a_line.offset.num = -1 * ((px * ay) - (py * ax)); + a_line.offset.denom = ax; + + Ratio r = intersect_x(b_line, a_line); + + if (!proper(r)) { + printf("bzzt\n"); + return 0; + } + + long b_x_movement = (r.num / r.denom); + long b_cost = b_x_movement / bx; + long a_x_movement = px - b_x_movement; + long a_cost = a_x_movement / ax; + printf("%d\n", b_cost + a_cost); + return b_cost + a_cost; +} + +int best_cost(int ax, int ay, int bx, int by, int px, int py) { + int best_cost_so_far = 0; + + for (int i = 0; i <= 100; i++) { + px -= ax; + py -= ay; + if (px % bx != 0 || py % by != 0) continue; + if (px / bx != py / by) continue; + + int cost = (i + 1) * 3 + px / bx; + if (best_cost_so_far == 0 || best_cost_so_far > cost) best_cost_so_far = cost; + } + + return best_cost_so_far; +} + +int main() { + int ax, ay, bx, by, px, py; + char *line; + + int cost = 0; + int cost_2 = 0; + while((line = aoc_read_line()) != NULL) { + sscanf(line, "Button A: X+%d, Y+%d", &ax, &ay); + sscanf(aoc_read_line(), "Button B: X+%d, Y+%d", &bx, &by); + sscanf(aoc_read_line(), "Prize: X=%d, Y=%d", &px, &py); + aoc_read_line(); + + cost += li_cost(ax, ay, bx, by, px, py); + cost_2 += li_cost(ax, ay, bx, by, px + 10000000000000, py + 10000000000000); + } + + printf("Part 1: %d\n", cost); + printf("Part 2: %lld\n", cost_2); + + aoc_free(); + return 0; +}