12.py 1.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960
  1. from queue import PriorityQueue
  2. DIRECTIONS = [(0, 1), (0, -1), (1, 0), (-1, 0)]
  3. grid = [[c for c in line.strip()] for line in open("12.input")]
  4. starts = []
  5. for y, line in enumerate(grid):
  6. for x, c in enumerate(line):
  7. if c == 'S':
  8. start = (x, y)
  9. grid[y][x] = 'a'
  10. elif c == 'E':
  11. end = (x, y)
  12. grid[y][x] = 'z'
  13. elif c == 'a':
  14. starts.append((x, y))
  15. size = (len(grid[0]), len(grid))
  16. def nxt(pos):
  17. x, y = pos
  18. locs = []
  19. for (dx, dy) in DIRECTIONS:
  20. if 0 <= x + dx and x + dx < size[0]:
  21. if 0 <= y + dy and y + dy < size[1]:
  22. if ord(grid[y + dy][x + dx]) - ord(grid[y][x]) <= 1:
  23. locs.append((x + dx, y + dy))
  24. return locs
  25. def search(grid, start, end):
  26. dists = {}
  27. dists[start] = 0
  28. queue = PriorityQueue()
  29. queue.put((0, start))
  30. while not queue.empty():
  31. _, current = queue.get()
  32. dist = dists[current]
  33. if current == end:
  34. return dist
  35. for loc in nxt(current):
  36. old_dist = dists.get(loc, 1000000)
  37. if dist + 1 < old_dist:
  38. dists[loc] = dist + 1
  39. queue.put((dists[loc], loc))
  40. return 10000000
  41. # Part 1
  42. print(search(grid, start, end))
  43. # Part 2, disgusting brute force. Could be done faster by inverting the
  44. # neighbour condition and searching from 'end' to any of the positions in
  45. # 'starts'.
  46. print(min(search(grid, start, end) for start in starts))