23_hike.py 1.4 KB

1234567891011121314151617181920212223242526272829303132333435363738394041
  1. #!/usr/bin/env python3
  2. import sys
  3. DXDY = {'^': [(0, -1)], 'v': [(0, 1)], '<': [(-1, 0)], '>': [(1, 0)],
  4. '.': [(0, -1), (0, 1), (-1, 0), (1, 0)]}
  5. def parse(inp):
  6. graph = {}
  7. lines = inp.split()
  8. for y, line in enumerate(lines):
  9. for x, char in enumerate(line):
  10. if char != '#':
  11. graph[(x, y)] = nbs = {}
  12. for dx, dy in DXDY[lines[y][x]]:
  13. nx, ny = nb = x + dx, y + dy
  14. if 0 <= ny < len(lines) and lines[ny][nx] != '#':
  15. nbs[nb] = 1
  16. for xy in [xy for xy, nbs in graph.items() if len(nbs) == 2]:
  17. (left, left_dist), (right, right_dist) = graph.pop(xy).items()
  18. left_nbs = graph[left]
  19. if xy in left_nbs:
  20. left_nbs[right] = left_nbs.pop(xy) + right_dist
  21. right_nbs = graph[right]
  22. if xy in right_nbs:
  23. right_nbs[left] = right_nbs.pop(xy) + left_dist
  24. return graph
  25. def longest_path(graph):
  26. start = next(iter(graph)) # python 3.8 guarantees insertion order
  27. end = next(reversed(graph))
  28. def dfs(xy, dist, vis):
  29. if xy == end:
  30. yield dist
  31. for nb, nbdist in graph[xy].items():
  32. if nb not in vis:
  33. yield from dfs(nb, dist + nbdist, vis | {nb})
  34. return max(dfs(start, 0, {start}))
  35. inp = sys.stdin.read()
  36. print(longest_path(parse(inp)))
  37. print(longest_path(parse(inp.translate(str.maketrans('<>^v', '....')))))