| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192 |
- import os, sys
- import numpy as np
- from queue import PriorityQueue
- from collections import defaultdict
- task_dir = os.path.dirname(__file__)
- sys.path.append(f"{task_dir}/..")
- from get_tasks import get_input, check_example, generate_readme
- def get_dirs(center, i_size, j_size, going_up=False, going_down=False):
- i, j = center
- up = max(0, i - 1), j
- left = i, max(0, j - 1)
- down = min(i + 1, i_size), j
- right = i, min(j_size, j + 1)
- if going_up:
- return up, left
- if going_down:
- return down, right
- return up, left, down, right
- def dijkstra(G, start=(0, 0), end=False, up=False, down=False):
- i_s, j_s = G.shape[0] - 1, G.shape[1] - 1
- end = (i_s, j_s) if not end else end
- path = []
- parents = {}
- visited = set()
- pq = PriorityQueue()
- nodeCosts = defaultdict(lambda: float("inf"))
- nodeCosts[start] = 0
- pq.put((0, start))
- def get_path(node):
- while node != start:
- path.append(node)
- prev_node = parents[node]
- node = prev_node
- path.append(start)
- return path[::-1]
- while pq:
- _, node = pq.get()
- if node == end:
- print("Get end!")
- return get_path(node), nodeCosts[end]
- visited.add(node)
- for adjNode in get_dirs(node, i_s, j_s, up, down):
- if adjNode in visited:
- continue
- newCost = nodeCosts[node] + G[adjNode]
- if nodeCosts[adjNode] > newCost:
- parents[adjNode] = node
- nodeCosts[adjNode] = newCost
- pq.put((newCost, adjNode))
- print("Can't get to the end!")
- return get_path(node), nodeCosts
- def part1(input: list[str]):
- ceiling = np.array([list(line) for line in input], dtype=int)
- _, cost = dijkstra(ceiling, down=True)
- print("The answer of part1 is:", cost)
- def part2(input: list[str]):
- ceiling = np.array([list(line) for line in input], dtype=int)
- full_ceiling = ceiling.copy()
- for step in range(1, 5):
- left_ceiling = ceiling + step
- left_ceiling[left_ceiling > 9] -= 9
- full_ceiling = np.hstack([full_ceiling, left_ceiling])
- line_ceiling = full_ceiling.copy()
- for step in range(1, 5):
- down_ceiling = line_ceiling + step
- down_ceiling[down_ceiling > 9] -= 9
- full_ceiling = np.vstack([full_ceiling, down_ceiling])
- _, cost = dijkstra(full_ceiling, down=True)
- print("The answer of part2 is:", cost)
- if __name__ == "__main__":
- input, example = get_input(task_dir, 15)
- check_example(example, part1)
- check_example(example, part2)
- part1(input)
- part2(input)
- generate_readme(task_dir, 15)
|