def captureImage(program): output = [[]] def handleOutput(x): if x == 10: output.append([]) else: output[-1].append(chr(x)) startNew(program, handleOutput) return [o for o in output if o]
def paint(program): colors = {(0,0):1} currentPosition = (0, 0) currentVelocity = (0, 1) output = [] state = startNew(program, lambda x: output.append(x)) while state: state = resumeWithInput(state, colors.get(currentPosition, 0)) color, direction = output output = [] colors[currentPosition] = color currentVelocity = rotate(currentVelocity, right=direction) x,y=currentPosition dx,dy = currentVelocity currentPosition = (x + dx, y + dy) coords = colors.keys() xs = list(map(lambda x: x[0], coords)) ys = list(map(lambda x: x[1], coords)) maxx = (max(xs)) maxy = (max(ys)) minx = (min(xs)) miny = (min(ys)) for y in range(maxy, miny-1,-1): row = ['#' if colors.get((x, y)) == 1 else ' ' for x in range(minx, maxx+1)] print(''.join(row))
def part2(program): totalElements = 50 outputQueues = [[] for _ in range(totalElements)] incomingQueues = [[] for _ in range(totalElements)] natValue = None natSeen = set() def generateHandler(i): return lambda x: outputQueues[i].append(x) def distributeQueues(i): outputQueue = outputQueues[i] while outputQueue: address = outputQueue.pop(0) x = outputQueue.pop(0) y = outputQueue.pop(0) if address == 255: return (x, y) else: incomingQueues[address].append((x, y)) return None computers = [ startNew(program, generateHandler(i)) for i in range(totalElements) ] for i, c in enumerate(computers): computers[i] = resumeWithInput(c, i) distributeQueues(i) while True: idleCount = 0 for i, c in enumerate(computers): if incomingQueues[i]: while incomingQueues[i]: x, y = incomingQueues[i].pop(0) gotX = resumeWithInput(c, x) computers[i] = resumeWithInput(gotX, y) else: idleCount += 1 computers[i] = resumeWithInput(c, -1) nextNat = distributeQueues(i) if nextNat: natValue = nextNat if idleCount == totalElements and not sum( 1 for i in incomingQueues if i): # All things are idle and nothing's incoming. Kick it in the trousers. if natValue in natSeen: return natValue incomingQueues[0].append(natValue) natSeen.add(natValue)
def part1(program): totalElements = 50 outputQueues = [[] for _ in range(totalElements)] incomingQueues = [[] for _ in range(totalElements)] specialOne = None def generateHandler(i): return lambda x: outputQueues[i].append(x) def distributeQueues(i): outputQueue = outputQueues[i] while outputQueue: address = outputQueue.pop(0) x = outputQueue.pop(0) y = outputQueue.pop(0) if address == 255: return (x, y) else: incomingQueues[address].append((x, y)) return None computers = [ startNew(program, generateHandler(i)) for i in range(totalElements) ] for i, c in enumerate(computers): computers[i] = resumeWithInput(c, i) distributeQueues(i) while not specialOne: for i, c in enumerate(computers): if incomingQueues[i]: while incomingQueues[i]: x, y = incomingQueues[i].pop(0) gotX = resumeWithInput(c, x) computers[i] = resumeWithInput(gotX, y) else: computers[i] = resumeWithInput(c, -1) special = distributeQueues(i) if special: return special
def runMaze(program): # Just set it big enough so we don't have to worry about expansion maze = [[MAZE_UNKNOWN] * 60 for _ in range(60)] start = (30, 30) setMaze(maze, start, MAZE_ORIGIN) output = [] initialState = startNew(program, lambda x: output.append(x)) pendingJunctions: List[Runner] = [Runner(initialState, start, 1)] visited = set(start) oxygen = None while pendingJunctions: currentRunner = pendingJunctions.pop() currentPosition = currentRunner.location state = currentRunner.state direction = currentRunner.direction while True: points = [Runner(state.fork(state.outputHandler), currentPosition, d) for d in DIRS if d != direction and getMaze(maze, applyDirection(currentPosition, d)) == MAZE_UNKNOWN] pendingJunctions.extend(points) nextPoint = applyDirection(currentPosition, direction) # Have we already been where we're about to go? No need to revisit. if getMaze(maze, nextPoint) != MAZE_UNKNOWN: break # Run as far as we can in a straight line state = resumeWithInput(state, direction) result = output.pop(0) if result == 0: # It is a wall. We can go no further setMaze(maze, nextPoint, MAZE_WALL) break elif result == 1: setMaze(maze, nextPoint, MAZE_VISITED) elif result == 2: setMaze(maze, nextPoint, MAZE_TARGET) oxygen = nextPoint currentPosition = nextPoint return maze, start, oxygen