def part_1():
    robot = Robot(Machine(load_tape('data/11-program.txt')), debug=False)
    grid = defaultdict(lambda: Color.NONE)
    robot.paint_on(grid)
    draw_grid(grid)
    count = sum(1 for color in grid.values() if color)
    print(f"painted on {count} cells")
Example #2
0
def part_2():
    tape = load_tape('data/13-program.txt')
    tape[0] = 2  # 2 quarters cheat
    m = Machine(tape, debug=False)
    game = m.run_control()

    screen = [[' ' for _ in range(SCREEN_WIDTH)] for _ in range(SCREEN_HEIGHT)]
    score = None

    paddle_x = None
    ball_x = None

    def joystick():
        if paddle_x is not None and ball_x is not None:
            return sgn(ball_x - paddle_x)
        else:
            return None

    try:
        while True:
            x = game.send(joystick())
            y = game.send(joystick())
            t = game.send(joystick())

            if x == -1 and y == 0:
                score = t
            elif 0 <= x < SCREEN_WIDTH and 0 <= y < SCREEN_HEIGHT:
                prev = screen[y][x]
                screen[y][x] = TILES[t]

                if t == 4:
                    ball_x = x
                elif prev == TILES[4]:
                    ball_x = None

                if t == 3:
                    paddle_x = x
                elif prev == TILES[3]:
                    paddle_x = None

                if prev == TILES[2] and t != 2:
                    print(f"destroyed ({x}, {y})")

            else:
                raise ValueError(f"out of bounds: x={x}, y{y}")

            if ball_x is not None and paddle_x is not None and score is not None:
                print()
                print(f"score: {score}")
                print('\n'.join(''.join(row) for row in screen))
                # time.sleep(.05)

    except StopIteration:
        pass
Example #3
0
def part_1():
    m = Machine(load_tape('data/13-program.txt'))

    def load_screen():
        seq = list(m.run_output_only())
        for h in range(0, len(seq), 3):
            x, y, t = seq[h:h+3]
            yield Point(x, y), t

    screen = list(load_screen())
    draw_screen(screen)
    blocks_count = sum(1 for p, t in screen if t == 2)
    print(f"part 1: blocks count is {blocks_count}")
def solution(fn: str):
    io = Machine(load_tape(fn)).run_io()

    commands = [
        'west', 'take mug', 'east', 'east', 'take coin', 'north', 'north',
        'take hypercube', 'south', 'south', 'south', 'west', 'take astrolabe',
        'north', 'east', 'north', 'east'
    ]

    for command in commands:
        print(io.read_str(), end='')
        print(f">>> {command}")
        io.write(command + "\n")
    print(io.read_str(), end='')
Example #5
0
def robot_run(*lines: str) -> Optional[int]:
    io = Machine(load_tape("data/21-program.txt")).run_io()
    print(io.read_str(), end='')

    script = "".join(line + "\n" for line in lines)
    print(script, end="")
    io.write(script)

    answer = list(io.read())
    if answer[-1] > 255:
        print(''.join(chr(v) for v in answer[:-1]), end="")
        return answer[-1]
    else:
        print(''.join(chr(v) for v in answer), end="")
        return None
Example #6
0
def part_2(screen):
    tape = load_tape("data/17-program.txt")
    assert tape[0] == 1
    tape[0] = 2  # control robot

    m = Machine(tape)
    io = m.run_io()

    script = """
        A,A,B,C,B,C,B,C,A,C
        R,6,L,8,R,8
        R,4,R,6,R,6,R,4,R,4
        L,8,R,6,L,10,L,10
    """

    lines = [
        line.strip() + '\n' for line in script.splitlines() if line.strip()
    ]
    assert len(lines) == 4

    draw_screen(io, screen)
    io.write(lines[0])  # main

    assert io.read_str() == "Function A:\n"
    io.write(lines[1])  # move function A

    assert io.read_str() == "Function B:\n"
    io.write(lines[2])  # move function B

    assert io.read_str() == "Function C:\n"
    io.write(lines[3])  # move function C

    assert io.read_str() == "Continuous video feed?\n"
    io.write("y\n" if screen else "n\n")  # video feed?

    dust = draw_screen(io, screen)
    print(f"dust: {dust}")
def solve(fn: str):
    io = Machine(load_tape(fn)).run_io()
    commands = [
        'west', 'take mug', 'north', 'take easter egg', 'south', 'east',
        'south', 'east', 'north', 'take candy cane', 'south', 'west', 'north',
        'east', 'take coin', 'north', 'north', 'take hypercube', 'south',
        'east', 'take manifold', 'west', 'south', 'south', 'east',
        'take pointer', 'west', 'west', 'take astrolabe', 'north', 'east',
        'north'
    ]
    items = [
        command[5:] for command in commands if command.startswith('take ')
    ]

    while commands:
        print(io.read_str(), end='')
        command = commands[0]
        del commands[0]
        print(f">>> {command}")
        io.write(command + '\n')

    print(io.read_str(), end='')

    co = generate_commands(items)
    commands = next(co)
    try:
        while True:
            last_output = None
            for command in commands:
                print(f">>> {command}")
                io.write(command + '\n')
                last_output = io.read_str()
                print(last_output, end='')
            # ...
            commands = co.send(int(input()))
    finally:
        pass
Example #8
0
def part_1():
    m = Machine(load_tape("data/17-program.txt"))
    screen_output = list(m.run_output_only())
    print(screen_output)
    lines = [
        line.strip()
        for line in ''.join(chr(v) for v in screen_output).splitlines()
        if line.strip()
    ]

    height = len(lines)
    width = len(lines[0])
    assert all(len(line) == width for line in lines)
    print(f"width={width}, height={height}")

    def cross(x, y):
        yield x, y
        yield x + 1, y
        yield x - 1, y
        yield x, y + 1
        yield x, y - 1

    intersections = {(x, y)
                     for x in range(1, width - 1)
                     for y in range(1, height - 1)
                     if all(lines[cy][cx] == '#' for cx, cy in cross(x, y))}

    print('\n'.join(''.join('O' if (x, y) in intersections else lines[y][x]
                            for x in range(width)) for y in range(height)))

    alignment = sum(x * y for x, y in intersections)

    print("intersections:")
    for x, y in intersections:
        print(f"> {x:2}, {y:2} -> {x*y:4}")
    print(f"total:     {alignment:5}")
Example #9
0
def map_maze():
    machine_f = Machine(load_tape("data/15-program.txt")).as_function_scalar()

    def sensor(heading: Heading) -> Tile:
        return Tile.from_code(machine_f(heading.code))

    step = 0
    robot = Robot(sensor)
    while True:
        step += 1
        robot.step()
        print(
            f"[R] {step}: pos={robot.pos}, distance={robot.current_distance}")

        if robot.current_tile == Tile.OXYGEN:
            robot.draw_plan()
            print(f"oxygen source located after {step} steps: "
                  f"pos={robot.pos}, "
                  f"distance={robot.current_distance}")
            print()
            break

    # continue as different "robot"
    step = 0
    oxbot = Robot(sensor, pos=robot.pos)
    while True:
        step += 1
        oxbot.step()
        print(
            f"[O] {step}: pos={oxbot.pos}, distance={oxbot.current_distance}")

        if oxbot.current_tile == Tile.OXYGEN:
            oxbot.draw_plan()
            max_oxygen_distance = max(oxbot.distances.values())
            print(f"max distance from oxygen source: {max_oxygen_distance}")
            break
Example #10
0
            assert list(m.run_output_only()) == []
            value = m.memory[0]
            if value == target_value:
                return noun, verb
    else:
        return None


def part_1(tape: list[int]):
    tape = list(tape)
    tape[1], tape[2] = 12, 2
    m = Machine(tape)
    assert list(m.run_output_only()) == []
    print(f"part 1: value at memory address 1 is {m.memory[0]}")


def part_2(tape: list[int]):
    tape = list(tape)
    answer = find_noun_verb(tape, target_value=19690720)
    if answer:
        noun, verb = answer
        print(f"part 2: noun={noun}, verb={verb}")
    else:
        print(f"part 2: answer not found")


if __name__ == '__main__':
    tape_ = load_tape("data/02-program.txt")
    part_1(tape_)
    part_2(tape_)
Example #11
0
def part_2():
    robot = Robot(Machine(load_tape('data/11-program.txt')), debug=False)
    grid2 = defaultdict(lambda: Color.NONE)
    grid2[Point(0, 0)] = Color.WHITE
    robot.paint_on(grid2)
    draw_grid(grid2)
Example #12
0
def run_network() -> int:
    tape = load_tape("data/23-program.txt")

    def create_network_io(address: int, debug: bool = False) -> MachineIO:
        machine = Machine(tape, name=f"M{address:02}", debug=debug)
        io = machine.run_io()
        # this is your address
        io.write_single(address)
        # and queue is empty
        io.write_single(-1)
        return io

    network: list[MachineIO] = [
        create_network_io(address) for address in range(50)
    ]
    queue: list[Packet] = []
    nat_packet: Optional[Packet] = None
    nat_sent_history: list[Packet] = []

    # initialize queue
    for address, io in enumerate(network):
        while io.state == IOState.OUTPUT:
            packet_out = Packet(*io.read(3))
            queue.append(packet_out)
            print(f"M{address:02}:{len(queue):02} queued {packet_out}")

    while True:
        # process queue until it's empty
        while queue:
            packet = queue.pop()
            address = packet.address

            if address == 255:
                nat_packet = packet
                print(f"NAT:{len(queue):02} receiving {packet}")
                continue

            io = network[address]
            assert io.state == IOState.INPUT
            io.write(packet)
            print(f"M{address:02}:{len(queue):02} receiving {packet}")

            while io.state == IOState.OUTPUT:
                packet_out = Packet(*io.read(3))
                queue.append(packet_out)
                print(f"M{address:02}:{len(queue):02} queued {packet_out}")

        if nat_packet:
            if nat_sent_history:
                previous_nat_packet = nat_sent_history[-1]
                if nat_packet.y == previous_nat_packet.y:
                    print(
                        f"NAT:{len(queue):02} repeating NAT packet Y detected: "
                        f"now={nat_packet}, prev={previous_nat_packet}")
                    return nat_packet.y
            nat_packet.address = 0
            print(
                f"NAT:{len(queue):02} queue is empty, queueing {nat_packet} to M00"
            )
            queue.append(nat_packet)
            nat_sent_history.append(nat_packet)
            nat_packet = None
        else:
            print(
                f"NAT:{len(queue):02} queue is empty and there's no NAT packet available"
            )
            return -1
Example #13
0
from y2019.intcode import load_tape
from y2019.intcode import Machine


if __name__ == '__main__':
    m = Machine(load_tape("data/09-program.txt"))

    result_1 = next(m.run_fixed_input([1]))
    print(f"part 1: {result_1}")

    result_2 = next(m.run_fixed_input([2]))
    print(f"part 2: {result_2}")
Example #14
0
from common.file import relative_path
from y2019.intcode import load_tape
from y2019.intcode import Machine

scan_machine = Machine(
    load_tape(relative_path(__file__, "data/19-program.txt")))
scan = scan_machine.as_function_scalar(restarting=True)


def part_1():
    total = 0
    for y in range(50):
        line = [scan(x, y) for x in range(50)]
        total += sum(line)
        print(''.join('#' if r else '.' for r in line))
    print(f"total: {total}")


def find_square(y_start: int = 20,
                x_start: tuple[int, int] = (14, 16),
                square_size: int = 100,
                debug: bool = False) -> tuple[int, int]:
    y = y_start
    x_min, x_max = x_start
    assert not scan(x_min - 1, y)
    assert scan(x_min, y)
    assert scan(x_max, y)
    assert not scan(x_max + 1, y)

    xs = {y: (x_min, x_max)}