def walk(data): exe = Executor(Code(data)) grid = {} queue = [Point(0, 0, [])] draw(0, 0, '.') breadth = True while True: p = queue.pop(0) # check each direction for i in (1, 2, 3, 4): nx = p.x + dx[i] ny = p.y + dy[i] if (nx, ny) in grid: continue # try this direction resp = exe.execute(i) assert resp in (0, 1, 2) if resp == 0: # wall, unchanged grid[nx, ny] = '#' draw(nx, ny, '#') elif resp in (1, 2): if resp == 2: part1 = len(p.walk) + 1 breadth = False c = '.' if resp == 1 else 'O' grid[nx, ny] = c draw(nx, ny, c) # moved - add to explore list if resp == 1: # Odd, if you explore from the oxygen we get an # assertion failure (ie position is off). if breadth: queue.append(Point(nx, ny, p.walk + [i])) else: queue.insert(0, Point(nx, ny, p.walk + [i])) # retrace step assert exe.execute(rev[i]) == 1 if not queue: break # optimisation: return to common point in next point np = queue[0] i = prefix(np.walk, p.walk) for j in reversed(p.walk[i:]): assert exe.execute(rev[j]) == 1 for j in np.walk[i:]: assert exe.execute(j) == 1 return part1, grid
def point(x, y): exe = Executor(code) return exe.execute(x, y)
def chain(code, phases): output = 0 for phase in phases: prog = Executor(code) output = prog.execute(phase, output) return output