usesbiggerwords

AoC Day 12 part 1

Dec 15th, 2021
251
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 2.85 KB | None | 0 0
  1. import enum
  2. import os
  3. from collections import defaultdict
  4. from typing import List, Tuple, DefaultDict
  5.  
  6.  
  7. class CaveType(enum.Enum):
  8.     SMALL = 0
  9.     LARGE = 1
  10.  
  11.  
  12. class Cave:
  13.     def __init__(self, name: str, cave_type: CaveType):
  14.         self.name = name
  15.         self.connected = []
  16.         self.type = cave_type
  17.  
  18.     def __eq__(self, other):
  19.         if isinstance(other, Cave):
  20.             return self.name == other.name
  21.         if isinstance(other, str):
  22.             return self.name == other
  23.  
  24.     def __repr__(self):
  25.         return repr(self.name)
  26.  
  27.     def __hash__(self):
  28.         return hash(self.name)
  29.  
  30.  
  31. def read_and_init(fn: str) -> Tuple[List[Cave], DefaultDict[Cave, List]]:
  32.     with open(fn, 'r') as f:
  33.         lines = f.read().splitlines()
  34.     cave_names = set()
  35.     for line in lines:
  36.         cave_name1, cave_name2 = line.split('-')
  37.         cave_names.add(cave_name1)
  38.         cave_names.add(cave_name2)
  39.     caves = [Cave(name, get_cave_type(name)) for name in cave_names]
  40.     graph = defaultdict(list)
  41.     for line in lines:
  42.         n1, n2 = line.split('-')
  43.         c1, c2 = get_by_name(caves, n1), get_by_name(caves, n2)
  44.         graph[c1].append(c2)
  45.         graph[c2].append(c1)
  46.     return caves, graph
  47.  
  48.  
  49. def get_by_name(caves: list, name: str) -> Cave:
  50.     search = [cave for cave in caves if cave == name]
  51.     if search:
  52.         return search.pop()
  53.  
  54.  
  55. def get_cave_type(name: str) -> CaveType:
  56.     if name.isupper():
  57.         return CaveType.LARGE
  58.     return CaveType.SMALL
  59.  
  60.  
  61. def dfs(caves: List[Cave],
  62.         graph: DefaultDict[Cave, List],
  63.         paths: list,
  64.         p: list,
  65.         current: Cave,
  66.         visited: set) -> Tuple[List[List[Cave]], List[Cave]]:
  67.     """
  68.    A recursive depth-first search.
  69.    :param graph:
  70.    :param visited:
  71.    :param caves:
  72.    :param paths:
  73.    :param p:
  74.    :param current:
  75.    :return:
  76.    """
  77.     visited.add(current)
  78.     p.append(current)
  79.     if current == 'end':
  80.         paths.append(p)
  81.         p = []
  82.         return paths, p
  83.     else:
  84.         valid_connections = [cave for cave in graph[current] if (cave.type == CaveType.LARGE) or (
  85.                 cave.type == CaveType.SMALL and cave not in visited)]
  86.         for cave in valid_connections:
  87.             paths, p = dfs(caves, graph, paths, p[:], cave, visited)
  88.         return paths, p
  89.  
  90.  
  91. def find_paths(caves: List[Cave], graph: DefaultDict[Cave, List]) -> List[List[Cave]]:
  92.     visited = set()
  93.     paths, _ = dfs(caves, graph, [], [], get_by_name(caves, 'start'), visited)
  94.     paths = [path for path in paths if 'start' in path and 'end' in path]
  95.     return paths
  96.  
  97.  
  98. def part1(caves: List[Cave], graph: DefaultDict[Cave, List[Cave]]):
  99.     paths = find_paths(caves, graph)
  100.     return len(paths)
  101.  
  102.  
  103. c, g = read_and_init(os.path.dirname(__file__) + '\\ex00.txt')
  104. result = part1(c, g)
  105. print('Part 1:', result)
Advertisement
Add Comment
Please, Sign In to add comment