mirror of
https://github.com/bertptrs/adventofcode.git
synced 2025-12-25 21:00:31 +01:00
2025 day 11 in Python
This commit is contained in:
10
2025/day11/README.md
Normal file
10
2025/day11/README.md
Normal 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
|
||||
```
|
||||
9
2025/day11/pyproject.toml
Normal file
9
2025/day11/pyproject.toml
Normal 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
10
2025/day11/sample.txt
Normal 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
14
2025/day11/sample2.txt
Normal 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
70
2025/day11/solve.py
Executable 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()
|
||||
Reference in New Issue
Block a user