78 lines
2.3 KiB
Python
78 lines
2.3 KiB
Python
|
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))
|