87
day12/day12.py
Executable file
87
day12/day12.py
Executable file
@@ -0,0 +1,87 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
import sys
|
||||||
|
from collections import defaultdict
|
||||||
|
from copy import deepcopy
|
||||||
|
from typing import DefaultDict, MutableMapping, Set
|
||||||
|
import pprint
|
||||||
|
import string
|
||||||
|
|
||||||
|
|
||||||
|
Vertices = DefaultDict[str, Set[str]]
|
||||||
|
SMALL = set(string.ascii_lowercase)
|
||||||
|
BIG = set(string.ascii_uppercase)
|
||||||
|
|
||||||
|
|
||||||
|
def is_small(cave: str):
|
||||||
|
s = set(cave)
|
||||||
|
return (s & SMALL) == s
|
||||||
|
|
||||||
|
|
||||||
|
def part1(vertices: Vertices):
|
||||||
|
small = {cave for cave in vertices.keys() if is_small(cave)}
|
||||||
|
big = set(vertices.keys()) - small
|
||||||
|
assert len(big & small) == 0
|
||||||
|
|
||||||
|
def find_paths(current: str, visited: Set[str] = set(), path: str = "") -> Set[str]:
|
||||||
|
visited = deepcopy(visited)
|
||||||
|
visited |= {current}
|
||||||
|
paths = set()
|
||||||
|
for vertex in vertices[current]:
|
||||||
|
if vertex == "end":
|
||||||
|
paths |= {path}
|
||||||
|
elif vertex in visited and vertex in small:
|
||||||
|
continue
|
||||||
|
else:
|
||||||
|
paths |= find_paths(vertex, visited, path + vertex)
|
||||||
|
return paths
|
||||||
|
|
||||||
|
paths = find_paths("start")
|
||||||
|
print(len(paths))
|
||||||
|
|
||||||
|
|
||||||
|
def part2(vertices: Vertices):
|
||||||
|
small = {cave for cave in vertices.keys() if is_small(cave)}
|
||||||
|
big = set(vertices.keys()) - small
|
||||||
|
assert len(big & small) == 0
|
||||||
|
|
||||||
|
def find_paths(
|
||||||
|
allowed: str,
|
||||||
|
current: str,
|
||||||
|
visited: MutableMapping[str, int] = defaultdict(lambda: 0),
|
||||||
|
path: str = "",
|
||||||
|
) -> Set[str]:
|
||||||
|
if current == allowed:
|
||||||
|
if visited[current] >= 2:
|
||||||
|
# This is a small cave and we've already visited it twice
|
||||||
|
return set()
|
||||||
|
elif current in small and visited[current]:
|
||||||
|
# Visited already
|
||||||
|
return set()
|
||||||
|
visited = deepcopy(visited)
|
||||||
|
visited[current] += 1
|
||||||
|
paths = set()
|
||||||
|
for vertex in vertices[current]:
|
||||||
|
if vertex == "end":
|
||||||
|
paths |= {path}
|
||||||
|
else:
|
||||||
|
paths |= find_paths(allowed, vertex, visited, path + vertex)
|
||||||
|
return paths
|
||||||
|
|
||||||
|
paths = set()
|
||||||
|
for allowed in small - {"start", "end"}:
|
||||||
|
paths |= find_paths(allowed, "start")
|
||||||
|
print(len(paths))
|
||||||
|
|
||||||
|
|
||||||
|
# Doing this comprehension so Mypy is happy
|
||||||
|
edges = [(a, b) for a, b in map(lambda l: l.strip().split("-"), sys.stdin)]
|
||||||
|
vertices: Vertices = defaultdict(set)
|
||||||
|
for a, b in edges:
|
||||||
|
vertices[a] |= {b}
|
||||||
|
vertices[b] |= {a}
|
||||||
|
|
||||||
|
|
||||||
|
print("Part 1")
|
||||||
|
part1(vertices)
|
||||||
|
print("Part 2")
|
||||||
|
part2(vertices)
|
||||||
7
day12/example.txt
Normal file
7
day12/example.txt
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
start-A
|
||||||
|
start-b
|
||||||
|
A-c
|
||||||
|
A-b
|
||||||
|
b-d
|
||||||
|
A-end
|
||||||
|
b-end
|
||||||
10
day12/example2.txt
Normal file
10
day12/example2.txt
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
dc-end
|
||||||
|
HN-start
|
||||||
|
start-kj
|
||||||
|
dc-start
|
||||||
|
dc-HN
|
||||||
|
LN-dc
|
||||||
|
HN-end
|
||||||
|
kj-sa
|
||||||
|
kj-HN
|
||||||
|
kj-dc
|
||||||
18
day12/example3.txt
Normal file
18
day12/example3.txt
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
fs-end
|
||||||
|
he-DX
|
||||||
|
fs-he
|
||||||
|
start-DX
|
||||||
|
pj-DX
|
||||||
|
end-zg
|
||||||
|
zg-sl
|
||||||
|
zg-pj
|
||||||
|
pj-he
|
||||||
|
RW-he
|
||||||
|
fs-DX
|
||||||
|
pj-RW
|
||||||
|
zg-RW
|
||||||
|
start-pj
|
||||||
|
he-WI
|
||||||
|
zg-he
|
||||||
|
pj-fs
|
||||||
|
start-RW
|
||||||
21
day12/input.txt
Normal file
21
day12/input.txt
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
ma-start
|
||||||
|
YZ-rv
|
||||||
|
MP-rv
|
||||||
|
vc-MP
|
||||||
|
QD-kj
|
||||||
|
rv-kj
|
||||||
|
ma-rv
|
||||||
|
YZ-zd
|
||||||
|
UB-rv
|
||||||
|
MP-xe
|
||||||
|
start-MP
|
||||||
|
zd-end
|
||||||
|
ma-UB
|
||||||
|
ma-MP
|
||||||
|
UB-xe
|
||||||
|
end-UB
|
||||||
|
ju-MP
|
||||||
|
ma-xe
|
||||||
|
zd-UB
|
||||||
|
start-xe
|
||||||
|
YZ-end
|
||||||
Reference in New Issue
Block a user