Added day 15

master
Tibor Bizjak 2023-03-14 22:07:11 +01:00
parent cf9d4e28e4
commit da8778d527
1 changed files with 129 additions and 0 deletions

129
day15.py 100644
View File

@ -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())