Added day 15
parent
cf9d4e28e4
commit
da8778d527
|
@ -0,0 +1,129 @@
|
|||
from intcode import Interpreter, WaitForInput
|
||||
|
||||
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'
|
||||
}
|
||||
|
||||
def move(pos, dir):
|
||||
if dir == NORTH:
|
||||
return pos[0], pos[1] + 1
|
||||
if dir == SOUTH:
|
||||
return pos[0], pos[1] - 1
|
||||
if dir == EAST:
|
||||
return pos[0] + 1, pos[1]
|
||||
if dir == WEST:
|
||||
return pos[0] - 1, pos[1]
|
||||
return NotImplemented
|
||||
|
||||
class DroidIO:
|
||||
def __init__(self):
|
||||
self._input = None
|
||||
self._output = None
|
||||
|
||||
def pop_input(self):
|
||||
i = self._input
|
||||
if i == None:
|
||||
raise WaitForInput
|
||||
self._input = None
|
||||
return i
|
||||
|
||||
def append_output(self, x):
|
||||
self._output = x
|
||||
|
||||
def flush(self):
|
||||
o = self._output
|
||||
self._output = None
|
||||
return o
|
||||
|
||||
def write(self, x):
|
||||
self._input = x
|
||||
|
||||
class Droid(Interpreter):
|
||||
def __init__(self, program):
|
||||
super().__init__(program, DroidIO)
|
||||
self.pos = 0, 0
|
||||
|
||||
def move(self, dir):
|
||||
out = self.eval(dir)
|
||||
if out != WALL:
|
||||
self.pos = move(self.pos, dir)
|
||||
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
|
||||
|
||||
def map_space(droid, map=None):
|
||||
if map == None:
|
||||
map = Map(ENCODING)
|
||||
for dir in DIRS:
|
||||
new_pos = move(droid.pos, dir)
|
||||
if new_pos in map:
|
||||
continue
|
||||
object = droid.move(dir)
|
||||
map[new_pos] = object
|
||||
if object == WALL:
|
||||
continue
|
||||
map_space(droid, map)
|
||||
droid.move(OPPOSITE[dir])
|
||||
return map
|
||||
|
||||
def shortest_paths(map, pos, visited=None):
|
||||
if visited == None:
|
||||
visited = {pos : 0}
|
||||
path = visited[pos] + 1
|
||||
for dir in DIRS:
|
||||
new = move(pos, dir)
|
||||
if map[new] == WALL or (new in visited and visited[new] <= path):
|
||||
continue
|
||||
visited[new] = path
|
||||
shortest_paths(map, new, visited)
|
||||
return visited
|
||||
|
||||
def preproc(puzzle_input):
|
||||
program = list(map(int, puzzle_input.split(',')))
|
||||
droid = Droid(program)
|
||||
area_map = map_space(droid)
|
||||
x, y = tuple(filter(lambda x: x[1]==OXY, area_map.items()))[0][0]
|
||||
path_map = shortest_paths(area_map, (x, y))
|
||||
return path_map
|
||||
|
||||
def partI(path_map):
|
||||
return path_map[(0, 0)]
|
||||
|
||||
def partII(path_map):
|
||||
return max(path_map.values())
|
Loading…
Reference in New Issue