Add day12

Signed-off-by: Alek Ratzloff <alekratz@gmail.com>
This commit is contained in:
2021-12-13 14:58:21 -08:00
parent 97a2d896f5
commit 7679363bb7
5 changed files with 143 additions and 0 deletions

87
day12/day12.py Executable file
View 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)