diff --git a/day13.py b/day13.py index 6ffca8a..374eba9 100644 --- a/day13.py +++ b/day13.py @@ -1,5 +1,3 @@ -# from sympy import solve -# from sympy.abc import x, y from math import lcm from tools.aoc import AOCDay from typing import Any @@ -8,14 +6,15 @@ BLOWUP_FACTOR = 10_000_000_000_000 def solve(machine: tuple[tuple[int, int], tuple[int, int], tuple[int, int]], part2: bool = False) -> tuple[int, int]: - # ax + by = c + # ax + by = c # for machine[a][0] and machine[b][0]; and again for machine[x][1] # y = (c - ax) / b - lcm_a = lcm(machine[0][0], machine[1][0]) + # And yes, I know I could have just used sympy or numpy, but I wanted to learn something; and this is fast enough + + lcm_a = lcm(machine[0][0], machine[0][1]) tmb_one = lcm_a / machine[0][0] - tmb_two = lcm_a / machine[1][0] + tmb_two = lcm_a / machine[0][1] a1 = machine[0][0] * tmb_one - a2 = machine[1][0] * tmb_two - b1 = machine[0][1] * tmb_one + b1 = machine[1][0] * tmb_one b2 = machine[1][1] * tmb_two if not part2: c1 = machine[2][0] * tmb_one @@ -24,20 +23,12 @@ def solve(machine: tuple[tuple[int, int], tuple[int, int], tuple[int, int]], par c1 = (machine[2][0] + BLOWUP_FACTOR) * tmb_one c2 = (machine[2][1] + BLOWUP_FACTOR) * tmb_two - ratio_a = a1 / a2 - ratio_b = b1 / b2 - ratio_c = c1 / c2 - - if ratio_a == ratio_b == ratio_c: - return -1, -1 # infinite many solutions - elif ratio_a == ratio_b and ratio_b != ratio_c: - return -1, -1 # no solutions + y = (c1 - c2) / (b1 - b2) + x = (c1 - (b1 * y)) / a1 + if x == int(x) and y == int(y): + return int(x), int(y) else: - y = (c1 - c2) / (b1 - b2) - x = (c1 - (b1 * y)) / a1 - return x, y - - pass + return -1, -1 class Day(AOCDay): @@ -66,44 +57,12 @@ class Day(AOCDay): return machines def part1(self) -> Any: - tokens = 0 - for machine in self.parse_input(): - x, y = solve(machine) - if x > 0 and y > 0: - print(machine, x, y, 3 * x + y) - tokens += 3 * x + y - return tokens - # found = False - # for ba_press in range(100): - # for bb_press in range(100): - # if ( - # ba_press * machine[0][0] + bb_press * machine[1][0] == machine[2][0] - # and ba_press * machine[0][1] + bb_press * machine[1][1] == machine[2][1] - # ): - # tokens += 3 * ba_press + bb_press - # found = True - # break - - # if found: - # break - - # return tokens + solves = [solve(machine) for machine in self.parse_input()] + return sum(3 * x + y for x, y in solves if x > 0) def part2(self) -> Any: - tokens = 0 - # for machine in self.parse_input(): - # ans = solve( - # [ - # machine[0][0] * x + machine[1][0] * y - (machine[2][0] + BLOWUP_FACTOR), - # machine[0][1] * x + machine[1][1] * y - (machine[2][1] + BLOWUP_FACTOR), - # ], - # [x, y], - # dict=True, - # ) - # if len(ans) == 1 and ans[0][x] == int(ans[0][x]) and ans[0][y] == int(ans[0][y]): - # tokens += 3 * ans[0][x] + ans[0][y] - - return tokens + solves = [solve(machine, part2=True) for machine in self.parse_input()] + return sum(3 * x + y for x, y in solves if x > 0) if __name__ == "__main__":