1
0

main.py 2.6 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192
  1. import os, sys
  2. import numpy as np
  3. from queue import PriorityQueue
  4. from collections import defaultdict
  5. task_dir = os.path.dirname(__file__)
  6. sys.path.append(f"{task_dir}/..")
  7. from get_tasks import get_input, check_example, generate_readme
  8. def get_dirs(center, i_size, j_size, going_up=False, going_down=False):
  9. i, j = center
  10. up = max(0, i - 1), j
  11. left = i, max(0, j - 1)
  12. down = min(i + 1, i_size), j
  13. right = i, min(j_size, j + 1)
  14. if going_up:
  15. return up, left
  16. if going_down:
  17. return down, right
  18. return up, left, down, right
  19. def dijkstra(G, start=(0, 0), end=False, up=False, down=False):
  20. i_s, j_s = G.shape[0] - 1, G.shape[1] - 1
  21. end = (i_s, j_s) if not end else end
  22. path = []
  23. parents = {}
  24. visited = set()
  25. pq = PriorityQueue()
  26. nodeCosts = defaultdict(lambda: float("inf"))
  27. nodeCosts[start] = 0
  28. pq.put((0, start))
  29. def get_path(node):
  30. while node != start:
  31. path.append(node)
  32. prev_node = parents[node]
  33. node = prev_node
  34. path.append(start)
  35. return path[::-1]
  36. while pq:
  37. _, node = pq.get()
  38. if node == end:
  39. print("Get end!")
  40. return get_path(node), nodeCosts[end]
  41. visited.add(node)
  42. for adjNode in get_dirs(node, i_s, j_s, up, down):
  43. if adjNode in visited:
  44. continue
  45. newCost = nodeCosts[node] + G[adjNode]
  46. if nodeCosts[adjNode] > newCost:
  47. parents[adjNode] = node
  48. nodeCosts[adjNode] = newCost
  49. pq.put((newCost, adjNode))
  50. print("Can't get to the end!")
  51. return get_path(node), nodeCosts
  52. def part1(input: list[str]):
  53. ceiling = np.array([list(line) for line in input], dtype=int)
  54. _, cost = dijkstra(ceiling, down=True)
  55. print("The answer of part1 is:", cost)
  56. def part2(input: list[str]):
  57. ceiling = np.array([list(line) for line in input], dtype=int)
  58. full_ceiling = ceiling.copy()
  59. for step in range(1, 5):
  60. left_ceiling = ceiling + step
  61. left_ceiling[left_ceiling > 9] -= 9
  62. full_ceiling = np.hstack([full_ceiling, left_ceiling])
  63. line_ceiling = full_ceiling.copy()
  64. for step in range(1, 5):
  65. down_ceiling = line_ceiling + step
  66. down_ceiling[down_ceiling > 9] -= 9
  67. full_ceiling = np.vstack([full_ceiling, down_ceiling])
  68. _, cost = dijkstra(full_ceiling, down=True)
  69. print("The answer of part2 is:", cost)
  70. if __name__ == "__main__":
  71. input, example = get_input(task_dir, 15)
  72. check_example(example, part1)
  73. check_example(example, part2)
  74. part1(input)
  75. part2(input)
  76. generate_readme(task_dir, 15)