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