Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- import enum
- import os
- from collections import defaultdict
- from typing import List, Tuple, DefaultDict
- class CaveType(enum.Enum):
- SMALL = 0
- LARGE = 1
- class Cave:
- def __init__(self, name: str, cave_type: CaveType):
- self.name = name
- self.connected = []
- self.type = cave_type
- def __eq__(self, other):
- if isinstance(other, Cave):
- return self.name == other.name
- if isinstance(other, str):
- return self.name == other
- def __repr__(self):
- return repr(self.name)
- def __hash__(self):
- return hash(self.name)
- def read_and_init(fn: str) -> Tuple[List[Cave], DefaultDict[Cave, List]]:
- with open(fn, 'r') as f:
- lines = f.read().splitlines()
- cave_names = set()
- for line in lines:
- cave_name1, cave_name2 = line.split('-')
- cave_names.add(cave_name1)
- cave_names.add(cave_name2)
- caves = [Cave(name, get_cave_type(name)) for name in cave_names]
- graph = defaultdict(list)
- for line in lines:
- n1, n2 = line.split('-')
- c1, c2 = get_by_name(caves, n1), get_by_name(caves, n2)
- graph[c1].append(c2)
- graph[c2].append(c1)
- return caves, graph
- def get_by_name(caves: list, name: str) -> Cave:
- search = [cave for cave in caves if cave == name]
- if search:
- return search.pop()
- def get_cave_type(name: str) -> CaveType:
- if name.isupper():
- return CaveType.LARGE
- return CaveType.SMALL
- def dfs(caves: List[Cave],
- graph: DefaultDict[Cave, List],
- paths: list,
- p: list,
- current: Cave,
- visited: set) -> Tuple[List[List[Cave]], List[Cave]]:
- """
- A recursive depth-first search.
- :param graph:
- :param visited:
- :param caves:
- :param paths:
- :param p:
- :param current:
- :return:
- """
- visited.add(current)
- p.append(current)
- if current == 'end':
- paths.append(p)
- p = []
- return paths, p
- else:
- valid_connections = [cave for cave in graph[current] if (cave.type == CaveType.LARGE) or (
- cave.type == CaveType.SMALL and cave not in visited)]
- for cave in valid_connections:
- paths, p = dfs(caves, graph, paths, p[:], cave, visited)
- return paths, p
- def find_paths(caves: List[Cave], graph: DefaultDict[Cave, List]) -> List[List[Cave]]:
- visited = set()
- paths, _ = dfs(caves, graph, [], [], get_by_name(caves, 'start'), visited)
- paths = [path for path in paths if 'start' in path and 'end' in path]
- return paths
- def part1(caves: List[Cave], graph: DefaultDict[Cave, List[Cave]]):
- paths = find_paths(caves, graph)
- return len(paths)
- c, g = read_and_init(os.path.dirname(__file__) + '\\ex00.txt')
- result = part1(c, g)
- print('Part 1:', result)
Advertisement
Add Comment
Please, Sign In to add comment