2025 day 11 in Python

This commit is contained in:
2025-12-11 09:44:39 +01:00
parent ff8b8dac0c
commit a8a1c85498
5 changed files with 113 additions and 0 deletions

10
2025/day11/README.md Normal file
View File

@@ -0,0 +1,10 @@
# Day 11: Python
Straightforward. Uses `networkx` because I thought it would be very helpful but it only really saves
me from writing a topological sort algorithm in the end.
```console
$ uv run ./solve.py input.txt
Part 1: secret
Part 2: secret
```

View File

@@ -0,0 +1,9 @@
[project]
name = "solve"
version = "0.1.0"
description = "Add your description here"
readme = "README.md"
requires-python = ">=3.13"
dependencies = [
"networkx>=3.6.1",
]

10
2025/day11/sample.txt Normal file
View File

@@ -0,0 +1,10 @@
aaa: you hhh
you: bbb ccc
bbb: ddd eee
ccc: ddd eee fff
ddd: ggg
eee: out
fff: out
ggg: out
hhh: ccc fff iii
iii: out

14
2025/day11/sample2.txt Normal file
View File

@@ -0,0 +1,14 @@
svr: aaa bbb
aaa: fft
fft: ccc
bbb: tty
tty: ccc
ccc: ddd eee
ddd: hub
hub: fff
eee: dac
dac: fff
fff: ggg hhh
ggg: out
hhh: out
you: out

70
2025/day11/solve.py Executable file
View File

@@ -0,0 +1,70 @@
#!/usr/bin/env python3
from collections import defaultdict
import fileinput
from typing import Iterable
import networkx as nx
def parse_graph() -> nx.Graph:
graph = nx.DiGraph()
for line in fileinput.input():
source, rem = line.split(": ")
for sink in rem.strip().split(" "):
graph.add_edge(source, sink)
return graph
def count(gen: Iterable) -> int:
return sum(1 for _ in gen)
def main() -> None:
graph = parse_graph()
# Observation: graph is a DAG, so one needs to go in front of the other. We can do this in three
# steps:
# svr → closest(dac, fft) -> furthest(dac,fft)
rank = {
node: rank
for rank, node in enumerate(nx.topological_sort(graph))
}
rev_rank = {rank: node for node, rank in rank.items()}
if rank["dac"] > rank["fft"]:
closest = "fft"
furthest = "dac"
else:
closest = "dac"
furthest = "fft"
def ranked_all_paths(source: str, dest: str) -> int:
counts = defaultdict(int)
counts[dest] = 1
for r in range(rank[dest], rank[source], -1):
node = rev_rank[r]
if node not in counts:
continue
for u, _ in graph.in_edges(node):
counts[u] += counts[node]
return counts[source]
assert nx.has_path(graph, closest, furthest)
print("Part 1", ranked_all_paths("you", "out"))
first = ranked_all_paths("svr", closest)
second = ranked_all_paths(closest, furthest)
third = ranked_all_paths(furthest, "out")
print("Part 2:", first * second * third)
if __name__ == "__main__":
main()