From 7679363bb7db0cafed7934cf5cf301c75e354ed8 Mon Sep 17 00:00:00 2001 From: Alek Ratzloff Date: Mon, 13 Dec 2021 14:58:21 -0800 Subject: [PATCH] Add day12 Signed-off-by: Alek Ratzloff --- day12/day12.py | 87 ++++++++++++++++++++++++++++++++++++++++++++++ day12/example.txt | 7 ++++ day12/example2.txt | 10 ++++++ day12/example3.txt | 18 ++++++++++ day12/input.txt | 21 +++++++++++ 5 files changed, 143 insertions(+) create mode 100755 day12/day12.py create mode 100644 day12/example.txt create mode 100644 day12/example2.txt create mode 100644 day12/example3.txt create mode 100644 day12/input.txt diff --git a/day12/day12.py b/day12/day12.py new file mode 100755 index 0000000..befb6f9 --- /dev/null +++ b/day12/day12.py @@ -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) diff --git a/day12/example.txt b/day12/example.txt new file mode 100644 index 0000000..6fd8c41 --- /dev/null +++ b/day12/example.txt @@ -0,0 +1,7 @@ +start-A +start-b +A-c +A-b +b-d +A-end +b-end diff --git a/day12/example2.txt b/day12/example2.txt new file mode 100644 index 0000000..ef30b81 --- /dev/null +++ b/day12/example2.txt @@ -0,0 +1,10 @@ +dc-end +HN-start +start-kj +dc-start +dc-HN +LN-dc +HN-end +kj-sa +kj-HN +kj-dc \ No newline at end of file diff --git a/day12/example3.txt b/day12/example3.txt new file mode 100644 index 0000000..da6e083 --- /dev/null +++ b/day12/example3.txt @@ -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 \ No newline at end of file diff --git a/day12/input.txt b/day12/input.txt new file mode 100644 index 0000000..6e568ac --- /dev/null +++ b/day12/input.txt @@ -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