|
| 1 | +data = open("input.txt", "r").read().strip().split("\n") |
| 2 | + |
| 3 | +import sys |
| 4 | +from collections import deque |
| 5 | + |
| 6 | +sys.setrecursionlimit(100000000) |
| 7 | + |
| 8 | +UP = (-1, 0) |
| 9 | +DOWN = (1, 0) |
| 10 | +LEFT = (0, -1) |
| 11 | +RIGHT = (0, 1) |
| 12 | +directions = [UP, DOWN, LEFT, RIGHT] |
| 13 | + |
| 14 | + |
| 15 | +def add_pair(a, b): |
| 16 | + return (a[0] + b[0], a[1] + b[1]) |
| 17 | + |
| 18 | + |
| 19 | +def in_grid(pos, grid): |
| 20 | + row, col = pos |
| 21 | + return 0 <= row < len(grid) and 0 <= col < len(grid[row]) |
| 22 | + |
| 23 | + |
| 24 | +def to_int(x): |
| 25 | + if x == "S": |
| 26 | + x = "a" |
| 27 | + elif x == "E": |
| 28 | + x = "z" |
| 29 | + return ord(x) - 96 |
| 30 | + |
| 31 | + |
| 32 | +def can_move(a, b, grid): |
| 33 | + a_r, a_c = a |
| 34 | + b_r, b_c = b |
| 35 | + a = to_int(grid[a_r][a_c]) |
| 36 | + b = to_int(grid[b_r][b_c]) |
| 37 | + |
| 38 | + return b - a <= 1 |
| 39 | + |
| 40 | + |
| 41 | +def get_neighbours(pos, grid): |
| 42 | + neighbours = [ |
| 43 | + add_pair(pos, d) for d in directions if in_grid(add_pair(pos, d), grid) |
| 44 | + ] |
| 45 | + neighbours = [x for x in neighbours if can_move(pos, x, grid)] |
| 46 | + return neighbours |
| 47 | + |
| 48 | + |
| 49 | +def bfs(starts, grid): |
| 50 | + seen = set() |
| 51 | + q = deque([(start, 0) for start in starts]) |
| 52 | + while q: |
| 53 | + pos, d = q.popleft() |
| 54 | + if grid[pos[0]][pos[1]] == "E": |
| 55 | + return d |
| 56 | + elif pos in seen: |
| 57 | + continue |
| 58 | + else: |
| 59 | + seen.add(pos) |
| 60 | + for neighbour in get_neighbours(pos, grid): |
| 61 | + q.append((neighbour, d + 1)) |
| 62 | + |
| 63 | + |
| 64 | +def part_one(data: list[str]): |
| 65 | + grid = [[*line] for line in data] |
| 66 | + |
| 67 | + for r in range(len(data)): |
| 68 | + for c in range(len(data[r])): |
| 69 | + if grid[r][c] == "S": |
| 70 | + return bfs([(r, c)], grid) |
| 71 | + |
| 72 | + |
| 73 | +def part_two(data: list[str]): |
| 74 | + grid = [[*line] for line in data] |
| 75 | + |
| 76 | + s = [] |
| 77 | + for r in range(len(data)): |
| 78 | + for c in range(len(data[r])): |
| 79 | + if grid[r][c] == "S" or grid[r][c] == "a": |
| 80 | + s.append((r, c)) |
| 81 | + |
| 82 | + return bfs(s, grid) |
| 83 | + |
| 84 | + |
| 85 | +if __name__ == "__main__": |
| 86 | + print(part_one(data)) |
| 87 | + print(part_two(data)) |
0 commit comments