11# Advent of code Day 10
22# https://adventofcode.com/2025/day/10
33# 10/12/2025
4-
4+
5+ from functools import cache
6+ import heapq
7+ from collections import defaultdict
8+ from tqdm .auto import tqdm
9+ from collections import deque
10+
11+ def parse (buttons : str ):
12+ buttons = buttons .strip ().split ()
13+ goal = tuple (map (lambda x : int (x == "#" ),
14+ buttons [0 ][1 :- 1 ]))
15+ size = len (goal )
16+ req = tuple (map (int , buttons [- 1 ][1 :- 1 ].split ("," )))
17+ buttons = list (map (
18+ lambda s : tuple (map (int , s [1 :- 1 ].split ("," ))),
19+ buttons [1 :- 1 ]))
20+ for i in range (len (buttons )):
21+ r = [0 for _ in range (size )]
22+ for j in buttons [i ]:
23+ r [j ] = 1
24+ buttons [i ] = tuple (r )
25+ return goal , buttons , req
26+
27+
28+ with open ("input.txt" ) as file :
29+ inp = list (
30+ map (
31+ parse ,
32+ file .readlines ()
33+ )
34+ )
35+
36+ @cache
37+ def apply (button , state , mod = 2 ):
38+ res = list (state )
39+ for i in range (len (res )):
40+ res [i ] += button [i ]
41+ if mod :
42+ res [i ] %= mod
43+ return tuple (res )
44+
45+ res1 , res2 = 0 , 0
46+ for goal , buttons , req in tqdm (inp ):
47+ n = len (goal )
48+ start = tuple (0 for _ in range (n ))
49+ visited = defaultdict (bool )
50+ heap = [(0 , start )]
51+
52+ while heap :
53+ presses , state = heapq .heappop (heap )
54+
55+ if visited [state ]: continue
56+ visited [state ] = True
57+
58+ if state == goal :
59+ res1 += presses
60+ break
61+
62+ for button in buttons :
63+ newState = apply (button , state )
64+ if visited [newState ]: continue
65+
66+ heapq .heappush (
67+ heap ,
68+ (presses + 1 , newState )
69+ )
70+
71+ from pulp import *
72+
73+ res2 = 0
74+ for goal , buttons , req in tqdm (inp ):
75+ # Create integer variables (x[i] = times button i is pressed)
76+ x = [LpVariable (f"x{ i } " , 0 , cat = 'Integer' ) for i in range (len (buttons ))]
77+
78+ # Create optimization problem (minimization by default)
79+ prob = LpProblem ()
80+
81+ # Objective: minimize total button presses
82+ prob += lpSum (x )
83+
84+ # Constraints: for each dimension, button presses must sum to goal
85+ for i in range (len (goal )):
86+ prob += lpSum (x [j ] * buttons [j ][i ] for j in range (len (buttons ))) == req [i ]
87+
88+ # Solve with no output
89+ prob .solve (PULP_CBC_CMD (msg = 0 ))
90+
91+ # If optimal solution found, add to result
92+ if prob .status == 1 :
93+ res2 += int (value (prob .objective ))
94+
95+
96+ print (res1 , res2 )
0 commit comments