# from sympy import solve # from sympy.abc import x, y from math import lcm from tools.aoc import AOCDay from typing import Any 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 # y = (c - ax) / b lcm_a = lcm(machine[0][0], machine[1][0]) tmb_one = lcm_a / machine[0][0] tmb_two = lcm_a / machine[1][0] a1 = machine[0][0] * tmb_one a2 = machine[1][0] * tmb_two b1 = machine[0][1] * tmb_one b2 = machine[1][1] * tmb_two if not part2: c1 = machine[2][0] * tmb_one c2 = machine[2][1] * tmb_two else: 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 else: y = (c1 - c2) / (b1 - b2) x = (c1 - (b1 * y)) / a1 return x, y pass class Day(AOCDay): inputs = [ [ (480, "input13_test"), (33427, "input13"), ], [ (91649162972270, "input13"), ], ] def parse_input(self) -> list[tuple[tuple[int, int], tuple[int, int], tuple[int, int]]]: machines = [] for machine in self.getMultiLineInputAsArray(): button_a = machine[0].split(": ")[1] button_a_x, button_a_y = (int(x[2:]) for x in button_a.split(", ")) button_b = machine[1].split(": ")[1] button_b_x, button_b_y = (int(x[2:]) for x in button_b.split(", ")) prize = machine[2].split(": ")[1] prize_x, prize_y = (int(x[2:]) for x in prize.split(", ")) machines.append(((button_a_x, button_a_y), (button_b_x, button_b_y), (prize_x, prize_y))) 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 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 if __name__ == "__main__": day = Day(2024, 13) day.run(verbose=True)