def part2(path): program = read_program(path) program[0] = 2 c = Computer(program) score = None paddle = None ball = None while c.ram[c.ip] != 99: # when prompted for controller input, have the paddle move toward the # ball, if their x coordinates are different if c.ram[c.ip] % 100 == 3: if paddle is None or ball is None: c.in_.append(0) elif paddle < ball: c.in_.append(1) elif paddle > ball: c.in_.append(-1) else: c.in_.append(0) c.step() if len(c.out) == 3: x, y, tile_id = (c.out.popleft() for _ in range(3)) if (x, y) == (-1, 0): score = tile_id elif tile_id == 3: paddle = x elif tile_id == 4: ball = x return score
def get_drone_status(ram, x, y): '''Return the status of the drone at coordinates (x,y), calculated by an Intcode computer using the supplied program.''' comp = Computer(ram) comp.in_.append(x) comp.in_.append(y) while not comp.out: comp.step() return comp.out.popleft()
def part1(path): c = Computer(read_program(path)) tiles = {id: set() for id in range(5)} while c.ram[c.ip] != 99: c.step() if len(c.out) == 3: x, y, tile_id = (c.out.popleft() for _ in range(3)) tiles[tile_id].add((x, y)) return len(tiles[2])
def partX(path, in_, debug=False): program = read_program(path) c = Computer(program) c.in_.append(in_) while c.ram[c.ip] != 99: c.step(debug) if len(c.out) != 1: print(f'WARNING: expected 1 output, received {len(c.out)} instead') print(f'c.out == {c.out}') return c.out[-1]
def part2(progpath, routpath): ram = get_program(progpath) ram[0] = 2 c = Computer(ram) with open(routpath, 'r') as fobj: routine = fobj.read() for char in routine: c.in_.append(ord(char)) #disable video feed c.in_.extend((ord('n'), ord('\n'))) while c.ram[c.ip] != 99: c.step() return c.out.pop()
def amplify_signal_with_feedback(program, phase, input_=0, debug=False): '''After final Computer outputs, feed signal back to first Computer. Continue until all Computers halt. Return final output of last Computer. ''' output = None computers = [Computer(program.copy()) for _ in range(len(phase))] # apply phases as first inputs to each Computer for n in range(len(phase)): computers[n].in_.append(phase[n]) # apply initial input to first Computer computers[0].in_.append(input_) c_ndx = 0 # while the final computer has not yet halted while computers[-1].ram[computers[-1].ip] != 99: c = computers[c_ndx] next_c = computers[(c_ndx + 1) % len(computers)] # process until the Computer halts or needs input while c.ram[c.ip] != 99 and (c.ram[c.ip] != 3 or c.in_): c.step(debug) # apply output to the next computer if c.out: c_out = c.out.popleft() next_c.in_.append(c_out) # if it's the last computer, save to the thruster output if c_ndx == len(computers) - 1: output = c_out # move on to next computer c_ndx = (c_ndx + 1) % len(computers) # return thruster output return output
def __init__(self, path, addr): '''Creates a new Network Interface Controller using the Intcode program at the specified path and the specified address.''' self._comp = Computer(read_program(path)) self._addr = addr self._comp.in_.append(addr) self.run()
def shell(path): '''Runs an interactive springdroid shell, using the Intcode program stored at the specified path.''' cmp = Computer(read_program(path)) while cmp.ram[cmp.ip] != 99: out = run(cmp) print(out, end='' if type(out) == str else '\n') while True: instr = input() add_statement(cmp, instr) if instr in ('WALK', 'RUN'): break print('exiting shell')
def run_program(path, start_white=False): '''Returns the Robot that runs the program loaded from path.''' program = read_program(path) c = Computer(program) r = Robot() paint_next = True if start_white: r.painted[(0, 0)] = 1 while c.ram[c.ip] != 99: if c.ram[c.ip] == 3: #waiting for input c.in_.append(r.get_color()) c.step() if c.out: out = c.out.popleft() if paint_next: r.paint(out) else: r.move(out) paint_next = not paint_next return r
def check_origin(path): '''Check if the origin contains the oxygen system. True if it does, False if it does not.''' robot = Computer(read_program(path)) # try each direction; if wall, try other direction if next_output(robot, 1) != 0: return next_output(robot, 2) == 2 elif next_output(robot, 2) != 0: return next_output(robot, 1) == 2 elif next_output(robot, 3) != 0: return next_output(robot, 4) == 2 elif next_output(robot, 4) != 0: return next_output(robot, 3) == 2 else: raise ValueError('surrounded by walls')
def amplify_signal(program, phase, input_=0, debug=False): '''Run the input through a sequence of Intcode Computers, using input as input to the first in the sequence. All Computers run the same program. Each Computer is initialized with its phase number and the output of the previous Computer in the sequence, or the input parameter if it is the first Computer. Returns output of the last Computer.''' computers = [Computer(program.copy()) for _ in range(len(phase))] for n in range(len(phase)): computers[n].in_.append(phase[n]) computers[n].in_.append(input_) # process until the Computer produces output while not computers[n].out: computers[n].step(debug) # save output to be used as the next input input_ = computers[n].out.popleft() # Return output of the final Computer in the sequence return input_
def get_map(path): '''Get a full map of the oxygen system layout. Assumes origin is traversable and is NOT and oxygen location. Returns tuple: element 0 is a dictionary of (x,y) coordinates mapped to traversable neighbors; element 1 is a set of oxygen locations. ''' map_ = {} oxygen = set() orig = (0, 0) orig_robot = Computer(read_program(path)) to_search = deque([(orig, orig_robot)]) while to_search: loc, robot = to_search.popleft() neighbors = [] for nb in get_neighbors(loc): if nb[1] == loc[1] - 1: dir_ = 1 # north elif nb[1] == loc[1] + 1: dir_ = 2 # south elif nb[0] == loc[0] - 1: dir_ = 3 # west elif nb[0] == loc[0] + 1: dir_ = 4 # east else: raise ValueError(f'illegal neighbor {nb} to location {loc}') out = next_output(robot, dir_) if out != 0: neighbors.append(nb) if nb not in map_: to_search.append((nb, robot.clone())) if out == 2: oxygen.add(nb) # move back dir_ = {1: 2, 2: 1, 3: 4, 4: 3}[dir_] next_output(robot, dir_) map_[loc] = neighbors return (map_, oxygen)
def get_scaffold(ram): '''Run the Intcode program to get the scaffold output.''' c = Computer(ram) while c.ram[c.ip] != 99: c.step() return ''.join([chr(s) for s in c.out]).strip().split('\n')