feat: add solution 2025/10
This commit is contained in:
3
data/example/2025/10.txt
Normal file
3
data/example/2025/10.txt
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
[.##.] (3) (1,3) (2) (2,3) (0,2) (0,1) {3,5,4,7}
|
||||||
|
[...#.] (0,2,3,4) (2,3) (0,4) (0,1,2) (1,2,3,4) {7,5,12,7,2}
|
||||||
|
[.###.#] (0,1,2,3,4) (0,3,4) (0,1,2,4,5) (1,2) {10,11,11,5,10,5}
|
||||||
@@ -1,2 +1,7 @@
|
|||||||
|
# cli
|
||||||
python-dotenv==1.2.1
|
python-dotenv==1.2.1
|
||||||
requests==2.32.5
|
requests==2.32.5
|
||||||
|
|
||||||
|
# solutions
|
||||||
|
numpy==2.3.5
|
||||||
|
scipy==1.16
|
||||||
|
|||||||
98
src/solution/year_2025/day_10.py
Normal file
98
src/solution/year_2025/day_10.py
Normal file
@@ -0,0 +1,98 @@
|
|||||||
|
import collections
|
||||||
|
import re
|
||||||
|
from typing import Any
|
||||||
|
|
||||||
|
import numpy as np
|
||||||
|
from scipy import optimize
|
||||||
|
|
||||||
|
|
||||||
|
def _parse_input(input_data: str):
|
||||||
|
res: list[tuple[int, list[list[int]], list[int]]] = []
|
||||||
|
|
||||||
|
for line in input_data.splitlines():
|
||||||
|
_state = re.findall(r"\[([.#]*)\]", line)[0]
|
||||||
|
state = sum(1 << i for i, x in enumerate(_state) if x == "#")
|
||||||
|
|
||||||
|
_buttons = re.findall(r"\(([0-9,]*)\)", line)
|
||||||
|
buttons = [[int(n) for n in m.split(",")] for m in _buttons]
|
||||||
|
|
||||||
|
_joltage = re.findall(r" {([0-9,]*)}$", line)[0].strip()
|
||||||
|
joltage = list(map(int, _joltage.split(",")))
|
||||||
|
|
||||||
|
res.append((state, buttons, joltage))
|
||||||
|
|
||||||
|
return res
|
||||||
|
|
||||||
|
|
||||||
|
def _bfs(end: int, neighs: list[int]) -> int:
|
||||||
|
start = 0
|
||||||
|
|
||||||
|
dq = collections.deque([(0, start)])
|
||||||
|
visited = {0}
|
||||||
|
|
||||||
|
while dq:
|
||||||
|
d, p = dq.popleft()
|
||||||
|
|
||||||
|
if p == end:
|
||||||
|
return d
|
||||||
|
|
||||||
|
for n in neighs:
|
||||||
|
np = p ^ n
|
||||||
|
|
||||||
|
if np in visited:
|
||||||
|
continue
|
||||||
|
|
||||||
|
visited.add(np)
|
||||||
|
dq.append((d + 1, np))
|
||||||
|
|
||||||
|
raise ValueError(f"unable to calibrate {end}")
|
||||||
|
|
||||||
|
|
||||||
|
def _milp(vecs: list[list[int]], goal: list[int]) -> int:
|
||||||
|
n = len(goal)
|
||||||
|
m = len(vecs)
|
||||||
|
|
||||||
|
a = np.zeros((n, m), dtype=int)
|
||||||
|
|
||||||
|
for j, vec in enumerate(vecs):
|
||||||
|
for i in vec:
|
||||||
|
a[i][j] = 1
|
||||||
|
|
||||||
|
c = np.ones(m)
|
||||||
|
b = np.array(goal)
|
||||||
|
|
||||||
|
constraints = optimize.LinearConstraint(a, b, b) # type: ignore
|
||||||
|
bounds = optimize.Bounds(0, np.inf)
|
||||||
|
integrality = np.ones(m)
|
||||||
|
|
||||||
|
result = optimize.milp(
|
||||||
|
c,
|
||||||
|
constraints=constraints,
|
||||||
|
bounds=bounds,
|
||||||
|
integrality=integrality,
|
||||||
|
)
|
||||||
|
|
||||||
|
return int(result.fun)
|
||||||
|
|
||||||
|
|
||||||
|
def part_1(input_data: str) -> Any:
|
||||||
|
parsed = _parse_input(input_data)
|
||||||
|
|
||||||
|
s = 0
|
||||||
|
for end, switches, _ in parsed:
|
||||||
|
neighs = [sum(1 << n for n in m) for m in switches]
|
||||||
|
s += _bfs(end, neighs)
|
||||||
|
|
||||||
|
return s
|
||||||
|
|
||||||
|
|
||||||
|
def part_2(input_data: str) -> Any:
|
||||||
|
return sum(_milp(vecs, goal) for _, vecs, goal in _parse_input(input_data))
|
||||||
|
|
||||||
|
|
||||||
|
def test_part_1(example_data):
|
||||||
|
assert part_1(example_data) == 7
|
||||||
|
|
||||||
|
|
||||||
|
def test_part_2(example_data):
|
||||||
|
assert part_2(example_data) == 33
|
||||||
Reference in New Issue
Block a user