Coverage for src\aoc2022\days\day12.py: 100%
43 statements
« prev ^ index » next coverage.py v7.0.0, created at 2022-12-23 05:19 +0000
« prev ^ index » next coverage.py v7.0.0, created at 2022-12-23 05:19 +0000
1from typing import Tuple
3import numpy as np
5from src.aoc2022 import utils
8def parse_data_to_array(raw_data: str) -> np.ndarray:
9 """
10 Parse the raw data into a 1D list of instruction sets
12 :param raw_data: Raw data containing numerical data
13 :type raw_data: str
15 :return: parsed matrix of values
16 :rtype: List[List[str]]
17 """
19 rows = []
21 base_value = ord("a")
23 start_pos = None
24 end_pos = None
26 for i, line in enumerate(raw_data.split("\n")): # row number
27 values = []
28 for j, char in enumerate(line.strip()): # col number
29 if char == "S":
30 values.append(0)
31 start_pos = (j, i)
32 elif char == "E":
33 values.append(ord("z") - base_value)
34 end_pos = (j, i)
35 else:
36 values.append(ord(char) - base_value)
37 rows.append(np.array(values))
39 return np.array(rows).transpose(), start_pos, end_pos
42def get_distance_matrix(data: np.ndarray, pos: Tuple[int, int]) -> np.ndarray:
43 """
44 Compute the breadth-first distance matrix from aa starting position
46 :param data: Height map for the traversal
47 :type data: np.ndarray
49 :param pos: starting position for the depth-first search
50 :type pos: Tuple[int, int]
52 :return: the shortest distance from the starting pos to all other points
53 :rtype: np.ndarray
54 """
55 distances = np.full(data.shape, -1)
56 distances[pos] = 0
57 visited = np.full(data.shape, 0, dtype=bool)
59 visit_stack = [pos]
61 max_x, max_y = data.shape
63 deltas = [
64 (-1, 0),
65 (1, 0),
66 (0, -1),
67 (0, 1),
68 ]
70 while len(visit_stack) > 0:
71 x, y = visit_stack.pop(0)
73 if visited[x, y]:
74 pass
75 else:
77 visited[x, y] = True
79 for dx, dy in deltas:
80 new_x = x + dx
81 new_y = y + dy
83 valid_x = new_x >= 0 and new_x < max_x
84 valid_y = new_y >= 0 and new_y < max_y
86 if valid_x and valid_y:
88 valid_pos = data[x, y] - data[new_x, new_y] <= 1
90 if valid_pos and (not visited[new_x, new_y]):
91 distances[new_x, new_y] = distances[x, y] + 1
92 visit_stack.append((new_x, new_y))
94 return distances
97if __name__ == "__main__": # pragma: no cover
99 raw_data = utils.get_raw_data("./src/aoc2022/data/day12.txt")
101 parsed_map, start, end = parse_data_to_array(raw_data)
103 distance_matrix = get_distance_matrix(parsed_map, end)
104 path_length = distance_matrix[start]
106 print(f"The shortest path is {path_length}")
108 values = [e for e in distance_matrix[parsed_map == 0] if e != -1]
109 closest_start = min(*values)
111 print(f"The closest start point is {closest_start}")