Exemplo n.º 1
0
def main():
    program = load_input("d17.txt")
    grid = Grid.build(program)

    junctions = grid.get_junctions()
    p1 = sum(j[0] * j[1] for j in junctions)
    print(f"Part 1: {p1}")

    routine, functions = grid.get_dust_routine()

    def encode(data):
        x = [ord(c) for c in list(data)] + [10]
        if len(x) > 20:
            raise ValueError(data)

        return x

    def encode_fn(data):
        fn = []
        elements = data.split(",")
        for e in elements:
            fn.append(e[0])
            fn.append(str(e[1:]))

        return encode(",".join(fn))

    cpu = IntCodeCPU(program)
    cpu.poke(0, 2)
    cpu.run(encode(routine))
    for f in functions:
        cpu.run(encode_fn(f[1]))

    cpu.run(encode("n"))

    print(f"Part 2: {cpu.pop_output()[-1]}")
Exemplo n.º 2
0
    def test_unsupported_intcode(self):
        program = [42]
        cpu = IntCodeCPU(program)
        with self.assertRaises(ValueError) as exc_ctx:
            cpu.run()

        self.assertEqual("Unsupported instr: 42", str(exc_ctx.exception))
Exemplo n.º 3
0
    def test_read_no_input(self):
        program = [3, 3, 99, 0]
        cpu = IntCodeCPU(program)

        res = cpu.run()
        self.assertEqual(InterruptCode.WAITING_ON_INPUT, res)

        self.assertEqual(0, cpu._ip)
Exemplo n.º 4
0
    def test_ld_invalid_mode(self):
        program = []
        cpu = IntCodeCPU(program)
        cpu._modes = [42]
        with self.assertRaises(ValueError) as exc_ctx:
            cpu._ld(0)

        self.assertEqual("Unsupported mode: 42", str(exc_ctx.exception))
Exemplo n.º 5
0
    def test_get_operation(self):
        params = (
            (1, (1, [])),
            (101102, (2, [1, 1, 0, 1])),
        )

        for op, expected in params:
            cpu = IntCodeCPU([op])
            self.assertEqual(expected, cpu._get_instruction())
Exemplo n.º 6
0
def get_thruster_output(program, phase_settings):
    outputs = []

    for ps in phase_settings:
        inputs = (ps, outputs[0] if outputs else 0)
        runner = IntCodeCPU(program, ps)
        runner.run(inputs)
        outputs = runner.pop_output()

    return outputs[0]
Exemplo n.º 7
0
    def test_relative_mode_addressing(self):
        program = [
            int(i) for i in
            "109,1,204,-1,1001,100,1,100,1008,100,16,101,1006,101,0,99".split(
                ",")
        ]
        cpu = IntCodeCPU(program[:])
        cpu.run()

        self.assertEqual(program, cpu.pop_output())
Exemplo n.º 8
0
def get_program_output(program, n=None, v=None):
    program = [int(i) for i in program.split(",")]
    if n is not None:
        program[1] = n
    if v is not None:
        program[2] = v

    icr = IntCodeCPU(program)
    icr.run()

    return icr.peek(0)
Exemplo n.º 9
0
def get_blocks_after_first_run(program):
    cpu = IntCodeCPU(program)
    cpu.run()
    output = cpu.pop_output()

    c = 0
    for i in range(2, len(output), 3):
        if output[i] == 2:
            c += 1

    return c
Exemplo n.º 10
0
def play(program, coins=2, render=False):
    if render:
        print("\033[2J")

    cpu = IntCodeCPU(program)
    cpu.poke(0, coins)

    interrupt = cpu.run()
    if interrupt != InterruptCode.WAITING_ON_INPUT:
        raise ValueError(f"Unexpected program state: Interrupt = {interrupt}")

    gs = GameState.init(cpu.pop_output())

    while True:
        delta = gs.ball_x - gs.paddle_x
        if delta > 0:
            in_ = (1, )
        elif delta < 0:
            in_ = (-1, )
        else:
            in_ = (0, )

        res = cpu.run(in_)
        gs.update(cpu.pop_output())

        if render:
            gs.render()
            sleep(0.015)

        if res is None:
            break

    return gs.score
Exemplo n.º 11
0
    def _get_runner(n):
        r = runners[n]
        if not r:
            r = IntCodeCPU(program, n)
            runners[n] = r

        return r
Exemplo n.º 12
0
    def build(cls, program):
        cpu = IntCodeCPU(program)
        res = cpu.run()
        if res is not None:
            raise ValueError(f"CPU raised an interrupt: {res}")

        grid = "".join([chr(i) for i in cpu.pop_output()])

        grid = [list(r) for r in grid.split("\n") if r]

        direction_chars = {d.value for d in Direction}

        for x, y in itertools.product(range(len(grid[0])), range(len(grid))):
            if grid[y][x] in direction_chars:
                pos = (x, y)
                dir_ = Direction(grid[y][x])
                grid[y][x] = "#"
                break
        else:
            raise ValueError("Vacuum not found")

        return cls(grid, pos, dir_)
Exemplo n.º 13
0
def run_robot(program, initial_coords, initial_color):
    panels = {initial_coords: Panel(*initial_coords, initial_color)}
    robot = Robot(*initial_coords)

    cpu = IntCodeCPU(program)

    while True:
        p = panels.get(robot.position)
        if not p:
            p = Panel(*robot.position)
            panels[robot.position] = p

        res = cpu.run((p.color.value, ))
        if res == InterruptCode.WAITING_ON_INPUT:
            c, td = cpu.pop_output()
            p.paint(Color(c))
            robot.turn(TurnDirection(td))
            robot.move_forward()
        else:
            break

    return panels
Exemplo n.º 14
0
def generate_floor(program):
    robot = Robot(0, 0, Direction.UP)
    floor = Map(robot)

    cpu = IntCodeCPU(program)

    interrupt = cpu.run()
    if interrupt != InterruptCode.WAITING_ON_INPUT:
        raise ValueError(f"Unexpected program state: Interrupt = {interrupt}")

    while True:
        res = cpu.run((robot.direction,))
        out = cpu.pop_output()
        if len(out) > 1:
            raise ValueError(f"Output too long: {out}")

        out = out[0]
        new_pos = robot.next_pos()
        if out == 0:
            floor.set_tile(new_pos.x, new_pos.y, Tile.WALL)
            robot.turn_left()
        elif out == 1:
            floor.set_tile(new_pos.x, new_pos.y, Tile.EMPTY)
            robot.set_pos(new_pos)
            robot.turn_right()
        elif out == 2:
            floor.set_tile(new_pos.x, new_pos.y, Tile.OXYGEN)
            floor.oxy_pos = Point(new_pos.x, new_pos.y)
            robot.set_pos(new_pos)
            robot.turn_right()
        else:
            raise ValueError(f"Invalid output: {out}")

        if res is None or robot.pos == floor.orig:
            break

    return floor
Exemplo n.º 15
0
    def test_big_numbers(self):
        program = "1102,34915192,34915192,7,4,7,99,0"
        cpu = IntCodeCPU(program)
        cpu.run()

        self.assertEqual([1219070632396864], cpu.pop_output())
Exemplo n.º 16
0
    def test_output_middle_number(self):
        program = "104,1125899906842624,99"
        cpu = IntCodeCPU(program[:])
        cpu.run()

        self.assertEqual([1125899906842624], cpu.pop_output())
Exemplo n.º 17
0
    def test_add(self):
        program = [1, 5, 6, 7, 99, 5, 8, 0]
        cpu = IntCodeCPU(program)
        cpu.run()

        self.assertEqual(13, cpu.peek(7))
Exemplo n.º 18
0
    def test_mul(self):
        program = [2, 5, 6, 7, 99, 5, 8, 0]
        cpu = IntCodeCPU(program)
        cpu.run()

        self.assertEqual(40, cpu.peek(7))
Exemplo n.º 19
0
def get_diagnostic_code(program, system_id):
    r = IntCodeCPU(program)
    r.run((system_id, ))

    return r.pop_output()[-1]
Exemplo n.º 20
0
    def test_beq_jump(self):
        program = [6, 5, 4, 42, 7, 0, 0, 99]
        cpu = IntCodeCPU(program)
        cpu.run()

        self.assertEqual(7, cpu._ip)
Exemplo n.º 21
0
def get_coords(program):
    cpu = IntCodeCPU(program)
    cpu.run((2,))
    output = cpu.pop_output()
    assert len(output) == 1
    return output[0]
Exemplo n.º 22
0
    def test_read_with_input(self):
        program = [3, 3, 99, 0]
        cpu = IntCodeCPU(program)
        cpu.run((42, ))

        self.assertEqual(42, cpu.peek(3))
Exemplo n.º 23
0
 def test_eq_is_not_equal(self):
     program = [8, 5, 6, 7, 99, 8, 5, 42]
     cpu = IntCodeCPU(program)
     cpu.run()
     self.assertEqual(0, cpu.peek(7))
Exemplo n.º 24
0
 def test_lt_is_lower(self):
     program = [7, 5, 6, 7, 99, 5, 8, 42]
     cpu = IntCodeCPU(program)
     cpu.run()
     self.assertEqual(1, cpu.peek(7))
Exemplo n.º 25
0
 def test_ld_mode_0(self):
     program = [0, 99]
     cpu = IntCodeCPU(program)
     cpu._modes = [0]
     self.assertEqual(99, cpu._ld(1))
Exemplo n.º 26
0
 def test_ld_mode_1(self):
     program = []
     cpu = IntCodeCPU(program)
     cpu._modes = [1]
     self.assertEqual(99, cpu._ld(99))
Exemplo n.º 27
0
def get_boost_keycode(program):
    cpu = IntCodeCPU(program)
    cpu.run((1,))
    output = cpu.pop_output()
    assert len(output) == 1
    return output[0]
Exemplo n.º 28
0
 def test_beq_no_jump(self):
     program = [6, 0, 3, 99, 0, 0, 0, 0]
     cpu = IntCodeCPU(program)
     cpu.run()
     self.assertEqual(3, cpu._ip)
Exemplo n.º 29
0
    def test_write(self):
        program = [4, 3, 99, 42]
        cpu = IntCodeCPU(program)
        cpu.run()

        self.assertEqual([42], cpu.pop_output())