advent-of-code-2019/day15.py

109 lines
2.5 KiB
Python
Raw Normal View History

2023-03-15 18:20:23 +01:00
#!/usr/bin/env python3
import intcode
2023-03-14 22:07:11 +01:00
NORTH = 1
SOUTH = 2
WEST = 3
EAST = 4
DIRS = [NORTH, SOUTH, EAST, WEST]
OPPOSITE = {NORTH : SOUTH,
SOUTH : NORTH,
EAST : WEST,
WEST : EAST
}
WALL = 0
EMPTY = 1
OXY = 2
ENCODING = {WALL : '#',
EMPTY : '.',
OXY : 'O'
}
2023-03-15 18:20:23 +01:00
def move(pos, d):
if d == NORTH:
2023-03-14 22:07:11 +01:00
return pos[0], pos[1] + 1
2023-03-15 18:20:23 +01:00
if d == SOUTH:
2023-03-14 22:07:11 +01:00
return pos[0], pos[1] - 1
2023-03-15 18:20:23 +01:00
if d == EAST:
2023-03-14 22:07:11 +01:00
return pos[0] + 1, pos[1]
2023-03-15 18:20:23 +01:00
if d == WEST:
2023-03-14 22:07:11 +01:00
return pos[0] - 1, pos[1]
return NotImplemented
2023-03-15 18:20:23 +01:00
class Droid:
2023-03-14 22:07:11 +01:00
def __init__(self, program):
self.pos = 0, 0
2023-03-15 18:20:23 +01:00
self.comp = intcode.emulator(program)
2023-03-14 22:07:11 +01:00
2023-03-15 18:20:23 +01:00
def move(self, d):
self.comp.write_input(d)
out = next(self.comp)
2023-03-14 22:07:11 +01:00
if out != WALL:
2023-03-15 18:20:23 +01:00
self.pos = move(self.pos, d)
2023-03-14 22:07:11 +01:00
return out
class Map(dict):
def __init__(self, encoding):
super().__init__()
self.encoding = encoding
def __str__(self):
xs, ys = tuple(zip(*self.keys()))
r = str()
for y in range(min(ys), max(ys)+1):
for x in range(min(xs), max(xs)+1):
if x == y == 0:
r += 'X'
elif (x, y) not in self:
r += ' '
else:
r += self.encoding[self[(x, y)]]
r += '\n'
return r
2023-03-15 18:20:23 +01:00
def map_space(droid, space_map=None):
if space_map == None:
space_map = Map(ENCODING)
for d in DIRS:
new_pos = move(droid.pos, d)
if new_pos in space_map:
2023-03-14 22:07:11 +01:00
continue
2023-03-15 18:20:23 +01:00
obj = droid.move(d)
space_map[new_pos] = obj
if obj == WALL:
2023-03-14 22:07:11 +01:00
continue
2023-03-15 18:20:23 +01:00
map_space(droid, space_map)
droid.move(OPPOSITE[d])
return space_map
2023-03-14 22:07:11 +01:00
2023-03-15 18:20:23 +01:00
def shortest_paths(space_map, pos, visited=None):
2023-03-14 22:07:11 +01:00
if visited == None:
visited = {pos : 0}
path = visited[pos] + 1
2023-03-15 18:20:23 +01:00
for d in DIRS:
new = move(pos, d)
if space_map[new] == WALL or (new in visited and visited[new] <= path):
2023-03-14 22:07:11 +01:00
continue
visited[new] = path
2023-03-15 18:20:23 +01:00
shortest_paths(space_map, new, visited)
2023-03-14 22:07:11 +01:00
return visited
def preproc(puzzle_input):
2023-03-15 18:20:23 +01:00
program = intcode.parse(puzzle_input)
2023-03-14 22:07:11 +01:00
droid = Droid(program)
2023-03-15 18:20:23 +01:00
space_map = map_space(droid)
x, y = tuple(filter(lambda x: x[1]==OXY, space_map.items()))[0][0]
path_map = shortest_paths(space_map, (x, y))
2023-03-14 22:07:11 +01:00
return path_map
def partI(path_map):
return path_map[(0, 0)]
def partII(path_map):
return max(path_map.values())