Ejemplo n.º 1
0
def partb(txt: str):
    network: list[IntcodeProgram] = []
    for network_address in range(50):
        p = IntcodeProgram.parse(txt)
        p.write_input(network_address)
        network.append(p)

    last_y_sent_by_nat = None
    nat = None
    while True:
        packets_sent = 0
        for p in network:
            p.run()
            if p.is_waiting_for_input():
                p.write_input(-1)
            p.run()
            if len(p.outputs) > 0:
                assert len(p.outputs) % 3 == 0
                while len(p.outputs) > 0:
                    packets_sent += 1
                    destination, x, y = (p.outputs.popleft() for _ in range(3))
                    if destination == 255:
                        nat = (x, y)
                    else:
                        network[destination].write_input(x)
                        network[destination].write_input(y)
        is_idle = packets_sent == 0
        if is_idle:
            x, y = nat
            if y == last_y_sent_by_nat:
                return last_y_sent_by_nat
            network[0].write_input(x)
            network[0].write_input(y)
            last_y_sent_by_nat = y
Ejemplo n.º 2
0
def parta(txt: str):
    screen = {}
    p = IntcodeProgram.parse(txt)
    p.run()
    for x, y, tile_id in chunk([*p.outputs], 3):
        screen[(x, y)] = tile_id
    return Counter(screen.values())[2]
Ejemplo n.º 3
0
def get_complete_map(txt: str):
    p = IntcodeProgram.parse(txt)
    p.run()
    grid = {}
    explore(p, grid)
    # print(display(grid)) # see the grid
    return grid
Ejemplo n.º 4
0
def partb(txt: str):
    screen = {}
    score = None
    p = IntcodeProgram.parse(txt)
    p[0] = 2
    ball_x, paddle_x = None, None
    while not p.terminated:
        p.run_next()
        if len(p.outputs) > 0 and len(p.outputs) % 3 == 0:
            x, y, tile_id = (p.outputs.popleft() for _ in range(3))
            if (x, y) == (-1, 0):
                score = tile_id
            else:
                screen[(x, y)] = tile_id
                if tile_id == 4:
                    ball_x = x
                elif tile_id == 3:
                    paddle_x = x
        if p.is_waiting_for_input():
            # print(display(screen, score))
            joystick = 0
            if ball_x != paddle_x:
                joystick = 1 if ball_x > paddle_x else -1
            p.write_input(joystick)
    return score
Ejemplo n.º 5
0
def partb(txt: str):
    for noun, verb in itertools.product(range(0, 100), repeat=2):
        p = IntcodeProgram.parse(txt)
        p[1] = noun
        p[2] = verb
        p.run()
        if p[0] == 19690720:
            return 100 * noun + verb
Ejemplo n.º 6
0
def test_rel_base():
    p = IntcodeProgram.parse("109,19,204,-34")
    p[1985] = 1234567890
    p._relative_base = 2000
    p.run_next()
    assert p._relative_base == 2019
    p.run_next()
    assert len(p.outputs) == 1
    assert p.outputs[0] == 1234567890
Ejemplo n.º 7
0
def partb(txt: str):
    p = IntcodeProgram.parse(txt)
    assert p[0] == 1
    p[0] = 2  # wake up the robot
    p.run()

    # get the initial video feed
    video_feed, _main_prompt = "".join(chr(c) for c in p.outputs).split("\n\n")

    # plan the route
    full = full_route(video_feed)
    plan = [",".join(x) for x in plan_route(full)]

    # input the plan
    for f in plan:
        for x in f:
            p.write_input(ord(x))
        p.write_input(ord("\n"))

    # # for continuous output (while testing)
    # p.write_input(ord("y"))
    # p.write_input(ord("\n"))
    # leftover = ""
    # while not p.terminated:
    #     try:
    #         p.run(max_steps=100)
    #     except:
    #         pass

    #     if len(p.outputs) > 0:
    #         if p.outputs[-1] in range(0x110000):
    #             leftover += "".join(chr(x) for x in p.outputs)
    #         else:
    #             leftover += "".join(chr(x) for x in [*p.outputs][:-1])
    #         # if we have one or more full screens
    #         if "\n\n" in leftover:
    #             chunks = leftover.split("\n\n")
    #             # print each full screen
    #             for c in chunks[:-1]:
    #                 print(c)
    #                 print()
    #             # and set leftover to whatever we didn't print
    #             leftover = chunks[-1]
    #         if p.outputs[-1] not in range(0x110000):
    #             return p.outputs[-1]
    #         p.outputs.clear()

    # no to continuous output
    p.write_input(ord("n"))
    p.write_input(ord("\n"))

    # execute
    p.run()
    return p.outputs[-1]
Ejemplo n.º 8
0
def parta(txt: str):
    m = 0
    for phase_setting_seq in itertools.permutations(range(5)):
        amplifiers = [IntcodeProgram.parse(txt) for _ in range(5)]
        prev = 0
        for a, n in zip(amplifiers, phase_setting_seq):
            a.write_input(n)
            a.write_input(prev)
            a.run()
            prev = a.outputs[0]
        m = max(m, prev)
    return m
Ejemplo n.º 9
0
def partb(txt: str):
    m = 0
    for phase_setting_seq in itertools.permutations(range(5, 10)):
        amplifiers = [IntcodeProgram.parse(txt) for _ in range(5)]
        for a, n in zip(amplifiers, phase_setting_seq):
            a.write_input(n)
        prev = 0
        while not amplifiers[-1].terminated:
            for a in amplifiers:
                a.write_input(prev)
                a.run()
                prev = a.outputs[-1]
        m = max(m, prev)
    return m
Ejemplo n.º 10
0
def send_cmd(p: IntcodeProgram, cmd: str | None):
    if cmd is not None:
        for c in cmd:
            p.write_input(ord(c))
        p.write_input(ord("\n"))
    p.run()
    output = "".join(chr(c) for c in p.outputs)
    last_output = output.split("\n\n\n")[-1]
    return last_output.strip()
Ejemplo n.º 11
0
def explore(p: IntcodeProgram, grid: dict, pos: complex = 0 + 0j):
    for command in range(1, 5):
        delta = MOVES[command]
        new_pos = pos + delta
        if new_pos not in grid:
            # try to move to new_pos
            p.write_input(command)
            p.run()
            # get result of trying to move
            status = p.outputs.popleft()
            grid[new_pos] = DISPLAY_CHAR_MAP[status]
            if status != 0:  # if we moved
                explore(p, grid, new_pos)  # explore from the new pos
                # after we're done exploring the branch, go back one step, so we can try the next move fom pos
                p.write_input(OPPOSITES[command])
                p.run()
                # pop the output from returning to where we came from. we know this is not a wall
                assert p.outputs.popleft() != 0
Ejemplo n.º 12
0
def parta(txt: str):
    network: list[IntcodeProgram] = []
    for network_address in range(50):
        p = IntcodeProgram.parse(txt)
        p.write_input(network_address)
        network.append(p)

    while True:
        for p in network:
            p.run()
            if p.is_waiting_for_input():
                p.write_input(-1)
            p.run()
            if len(p.outputs) > 0:
                assert len(p.outputs) % 3 == 0
                while len(p.outputs) > 0:
                    destination, x, y = (p.outputs.popleft() for _ in range(3))
                    if destination == 255:
                        return y
                    network[destination].write_input(x)
                    network[destination].write_input(y)
Ejemplo n.º 13
0
def parta(txt: str):
    p = IntcodeProgram.parse(txt)

    ship_map = {}
    location = handle_move(p, None, ship_map, None)

    explore(p, ship_map, location)

    # move to the security checkpoint
    TARGET_ROOM = "Security Checkpoint"
    path_to_checkpoint = pathfind(location, TARGET_ROOM, ship_map)
    for direction in path_to_checkpoint:
        location = handle_move(p, direction, ship_map, location)

    # direction to move once in security checkpoint
    direction = next(d for d, l in get_doors(ship_map, location).items()
                     if l == TARGET_ROOM)

    # get past the security checkpoint
    all_items = get_inventory(p)
    for size in range(len(all_items)):
        for perm in itertools.combinations(all_items, r=size):
            # get the right items
            perm = set(perm)
            inv = get_inventory(p)
            to_drop = inv - perm
            to_take = perm - inv
            for item in to_drop:
                drop(p, item)
            for item in to_take:
                take(p, item)
            # try to enter
            result = send_cmd(p, direction)
            # if we're in a new location, it worked!
            if not result.startswith(f"== {TARGET_ROOM} =="):
                return next(int(x) for x in result.split() if x.isnumeric())
Ejemplo n.º 14
0
def test_parameter_modes():
    p = IntcodeProgram.parse("1002,4,3,4,33")
    p.run()
    assert ",".join(map(str, p.memory)) == "1002,4,3,4,99"
Ejemplo n.º 15
0
 def is_affected(x, y):
     p = IntcodeProgram(program)
     p.write_input(x)
     p.write_input(y)
     p.run()
     return bool(p.outputs[-1])
Ejemplo n.º 16
0
def test_negative_int():
    p = IntcodeProgram.parse("1101,100,-1,4,0")
    p.run()
    assert p[4] == 99
Ejemplo n.º 17
0
def test_output_sixteen_digit_number():
    p = IntcodeProgram.parse("1102,34915192,34915192,7,4,7,99,0")
    p.run()
    assert len(p.outputs) == 1
    assert len(str(p.outputs[0])) == 16
Ejemplo n.º 18
0
def helper(program, input, expected):
    p = IntcodeProgram.parse(program)
    p.write_input(input)
    p.run()
    assert len(p.outputs) == 1 and p.outputs[0] == expected
Ejemplo n.º 19
0
def parta(txt: str):
    p = IntcodeProgram.parse(txt)
    p[1] = 12
    p[2] = 2
    p.run()
    return p[0]
Ejemplo n.º 20
0
def parta(txt: str):
    p = IntcodeProgram.parse(txt)
    p.run()
    video_feed = "".join(chr(c) for c in p.outputs)
    return sum_of_alignment_parameters(video_feed)
Ejemplo n.º 21
0
def test_output_large_number():
    p = IntcodeProgram.parse("104,1125899906842624,99")
    p.run()
    assert len(p.outputs) == 1
    assert p.outputs[0] == 1125899906842624
Ejemplo n.º 22
0
def partb(txt: str):
    p = IntcodeProgram.parse(txt)
    p.write_input(5)
    p.run()
    assert len(p.outputs) == 1
    return p.outputs[0]
Ejemplo n.º 23
0
def test_quine():
    quine = "109,1,204,-1,1001,100,1,100,1008,100,16,101,1006,101,0,99"
    p = IntcodeProgram.parse(quine)
    p.run()
    assert ",".join(map(str, p.outputs)) == quine
Ejemplo n.º 24
0
def parta(txt: str):
    p = IntcodeProgram.parse(txt)
    p.write_input(1)
    p.run()
    assert all(n == 0 for n in [*p.outputs][:-1])
    return p.outputs[-1]