Пример #1
0
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
Пример #2
0
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()
Пример #3
0
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])
Пример #4
0
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]
Пример #5
0
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()
Пример #6
0
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
Пример #7
0
 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()
Пример #8
0
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')
Пример #9
0
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
Пример #10
0
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')
Пример #11
0
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_
Пример #12
0
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)
Пример #13
0
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')