from argparse import ArgumentParser def parse_line(line: str) -> tuple[int, int]: line = line.strip() parts = line.split(':', 1) coords_part = parts[1].strip() x_part, y_part = coords_part.split(',') x_val = x_part.strip()[1:] y_val = y_part.strip()[1:] return int(x_val), int(y_val) def is_solvable(XA, YA, XB, YB, Xp, Yp, max_presses=100): best_cost = None for a in range(max_presses+1): for b in range(max_presses+1): X = XA * a + XB * b Y = YA * a + YB * b if X == Xp and Y == Yp: cost = 3*a + b if best_cost is None or cost < best_cost: best_cost = cost return best_cost def format_buttons(a: str, b: str, prize: str) -> dict: XA, YA = parse_line(a) XB, YB = parse_line(b) _, p_coords = prize.split(':', 1) p_coords = p_coords.strip() # p_coords = "X=8400, Y=5400" x_part, y_part = p_coords.split(',') Xp = int(x_part.strip()[2:]) Yp = int(y_part.strip()[2:]) return { "A": {"X": XA, "Y": YA}, "B": {"X": XB, "Y": YB}, "PRIZE": {"X": Xp, "Y": Yp} } def main(machines: list[list[str]]) -> int: results = [] for part in machines: button_a = part[0] button_b = part[1] prize = part[2] formatted = format_buttons(button_a, button_b, prize) XA, YA = formatted["A"]["X"], formatted["A"]["Y"] XB, YB = formatted["B"]["X"], formatted["B"]["Y"] Xp, Yp = formatted["PRIZE"]["X"], formatted["PRIZE"]["Y"] cost = is_solvable(XA, YA, XB, YB, Xp, Yp, max_presses=100) if cost is not None: results.append(cost) if not results: return 0 return sum(results) def parse_input(input_file) -> list[list[str]]: with open(input_file, "r") as f: content = f.read().strip() machine_blocks = content.split("\n\n") machines = [] for block in machine_blocks: lines = block.strip().splitlines() if len(lines) == 3: machines.append(lines) return machines if __name__ == "__main__": parser = ArgumentParser(description="Solve claw machine problem") parser.add_argument("-f", "--file", required=True, help="Input file") args = parser.parse_args() input_data = parse_input(args.file) print(main(input_data))