110 lines
2.3 KiB
Python
110 lines
2.3 KiB
Python
![]() |
import sys
|
||
|
sys.path.append('../aoclib')
|
||
|
|
||
|
from aoclib import Input
|
||
|
import heapq
|
||
|
sys.setrecursionlimit(15000)
|
||
|
|
||
|
L = '<'
|
||
|
U = '^'
|
||
|
R = '>'
|
||
|
D = 'v'
|
||
|
|
||
|
EMPTY = '.'
|
||
|
WALL = '#'
|
||
|
START = 'S'
|
||
|
END = 'E'
|
||
|
|
||
|
|
||
|
class Maze:
|
||
|
def __init__(self, lines: list[list[str]]):
|
||
|
self.grid = lines
|
||
|
for y in range(len(self.grid)):
|
||
|
for x in range(len(self.grid[0])):
|
||
|
if self.grid[y][x] == START:
|
||
|
self.s = (x, y)
|
||
|
elif self.grid[y][x] == END:
|
||
|
self.e = (x, y)
|
||
|
|
||
|
def __str__(self):
|
||
|
grid = [r.copy() for r in self.grid]
|
||
|
return '\n'.join(''.join(row) for row in grid)
|
||
|
|
||
|
def start(self) -> tuple[int, int]:
|
||
|
return self.s
|
||
|
|
||
|
def end(self, pos: tuple[int, int]) -> bool:
|
||
|
return self.e == pos
|
||
|
|
||
|
def is_wall(self, pos) -> bool:
|
||
|
x, y = pos
|
||
|
return self.grid[y][x] == WALL
|
||
|
|
||
|
|
||
|
def search(m: Maze) -> int:
|
||
|
x, y = m.start()
|
||
|
state = (x, y, 1, 0)
|
||
|
|
||
|
queue = []
|
||
|
visited = set()
|
||
|
heapq.heappush(queue, (0, state))
|
||
|
visited.add(state)
|
||
|
|
||
|
while queue:
|
||
|
cost, state = heapq.heappop(queue)
|
||
|
x, y, xd, yd = state
|
||
|
|
||
|
if m.end((x, y)):
|
||
|
return cost
|
||
|
|
||
|
options = [
|
||
|
# move forward
|
||
|
(cost+1, (x+xd, y+yd, xd, yd)),
|
||
|
# turn
|
||
|
(cost+1000, (x, y, -yd, xd)),
|
||
|
(cost+1000, (x, y, yd, -xd)),
|
||
|
]
|
||
|
|
||
|
for opt in options:
|
||
|
cost, state = opt
|
||
|
x, y, _, _ = state
|
||
|
if m.is_wall((x, y)):
|
||
|
continue
|
||
|
if state in visited:
|
||
|
continue
|
||
|
|
||
|
visited.add(state)
|
||
|
heapq.heappush(queue, (cost, state))
|
||
|
return -1
|
||
|
|
||
|
def solve1(lines: list[list[str]]):
|
||
|
m = Maze(lines)
|
||
|
res = search(m)
|
||
|
return res
|
||
|
|
||
|
|
||
|
def solve2(lines: list[list[str]]):
|
||
|
maze = Maze(lines)
|
||
|
return ''
|
||
|
|
||
|
|
||
|
if __name__ == '__main__':
|
||
|
lines = Input('input_test.txt').lines_as_lists()
|
||
|
#part 1
|
||
|
print('test part 1:', solve1(lines))
|
||
|
#part 2
|
||
|
print('test part 2:', solve2(lines))
|
||
|
|
||
|
lines = Input('input_test2.txt').lines_as_lists()
|
||
|
#part 1
|
||
|
print('test 2 part 1:', solve1(lines))
|
||
|
#part 2
|
||
|
print('test 2 part 2:', solve2(lines))
|
||
|
|
||
|
lines = Input('input.txt').lines_as_lists()
|
||
|
#part 1
|
||
|
print('part 1:', solve1(lines)) # 90460
|
||
|
|
||
|
#part 2
|
||
|
print('part 2:', solve2(lines))
|