1
0

main.py 2.8 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394
  1. import os, sys
  2. import numpy as np
  3. from queue import PriorityQueue
  4. from collections import defaultdict, deque
  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):
  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. return up, left, down, right
  15. def dijkstra(G, start=(0, 0), end=False, pq=True, star=False):
  16. i_s, j_s = G.shape[0] - 1, G.shape[1] - 1
  17. end = (i_s, j_s) if not end else end
  18. parents = {}
  19. q = PriorityQueue() if pq else deque()
  20. nodeCosts = defaultdict(lambda: float("inf"))
  21. nodeCosts[start] = 0
  22. if pq:
  23. q.put((0, start))
  24. else:
  25. q.append((0, start))
  26. def get_path(node):
  27. path = []
  28. while node != start:
  29. path.append(node)
  30. node = parents[node]
  31. path.append(start)
  32. return path[::-1]
  33. def estimate(end, node):
  34. return abs(end[0] - node[0]) + abs(end[1] - node[1])
  35. acc = 0
  36. while (q.qsize() if pq else len(q)) != 0:
  37. acc += 1
  38. _, node = q.get() if pq else q.popleft()
  39. if pq and node == end:
  40. print("With early stop!", acc)
  41. return get_path(node), nodeCosts[node]
  42. for adjNode in get_dirs(node, i_s, j_s):
  43. newCost = nodeCosts[node] + G[adjNode]
  44. if nodeCosts[adjNode] > newCost:
  45. parents[adjNode] = node
  46. nodeCosts[adjNode] = newCost
  47. if star:
  48. newCost += estimate(end, adjNode)
  49. if pq:
  50. q.put((newCost, adjNode))
  51. else:
  52. q.append((newCost, adjNode))
  53. return get_path(end), nodeCosts[end]
  54. def part1(input: list[str]):
  55. ceiling = np.array([list(line) for line in input], dtype=int)
  56. _, cost = dijkstra(ceiling)
  57. print("The answer of part1 is:", cost)
  58. def part2(input: list[str], pq=True, star=False):
  59. ceiling = np.array([list(line) for line in input], dtype=int)
  60. full_ceiling = ceiling.copy()
  61. for step in range(1, 5):
  62. left_ceiling = ceiling + step
  63. left_ceiling[left_ceiling > 9] -= 9
  64. full_ceiling = np.hstack([full_ceiling, left_ceiling])
  65. line_ceiling = full_ceiling.copy()
  66. for step in range(1, 5):
  67. down_ceiling = line_ceiling + step
  68. down_ceiling[down_ceiling > 9] -= 9
  69. full_ceiling = np.vstack([full_ceiling, down_ceiling])
  70. _, cost = dijkstra(full_ceiling, pq=pq, star=star)
  71. print("The answer of part2 is:", cost)
  72. if __name__ == "__main__":
  73. input, example = get_input(task_dir, 15)
  74. check_example(example, part1)
  75. check_example(example, part2)
  76. part1(input)
  77. part2(input)
  78. generate_readme(task_dir, 15)