Exemplo n.º 1
0
def solve_day_11(input):
    # Instead of using a set for what panels have been painted
    # to see how many panels the robot paints at least once
    # I am just gonna gamble that part 2 asks about what was painted
    # so I can just go and print this dict
    panels = {}
    robot = Robot()
    regex = re.compile("-{0,1}\d+")
    f = open(input, "r")
    computer = IntCodeComputer(regex.findall(f.readline()))
    # computer.write(0) # Use this to start on a black panel for part 1
    computer.write(1)  # Use this to start on a white panel for part 2
    computer.run()
    output = computer.read()
    paint_as = output[0]
    turn = output[1]
    panels[(robot.x, robot.y)] = paint_as
    robot.turn(turn)
    robot.move()
    while computer.status != Status.TERMINATED:
        if (robot.x, robot.y) in panels:
            computer.write(panels[(robot.x, robot.y)])
        else:
            computer.write(0)
        computer.run()
        output = computer.read()
        paint_as = output[0]
        turn = output[1]
        panels[(robot.x, robot.y)] = paint_as
        robot.turn(turn)
        robot.move()
    pretty_print(panels)
    return len(panels)
Exemplo n.º 2
0
def turtle(start_panel_colour):

    x, y, heading = 0, 0, N  # turtle start state
    grid = {}  # grid coordinates with colour values

    computer = IntCodeComputer(puzzle_input)
    # add current colour to computer input queue
    computer.input_queue.append(start_panel_colour)
    paint_colour = computer.run()  # get new paint brush colour

    while not computer.opcode == Opcode.HALT:

        grid[(x, y)] = paint_colour

        turn_direction = computer.run()
        # turn direction = 0 is left, turn direction = 1  is right
        heading = [L, R][turn_direction][heading]
        x, y = x + heading[X_INCREMENT_INDEX], y + heading[Y_INCREMENT_INDEX]

        # get current colour, if not already seen it will be black
        current_colour = grid.get((x, y), BLACK)

        # add current colour to computer input queue
        computer.input_queue.append(current_colour)
        paint_colour = computer.run()  # current paint brush colour

    return grid
Exemplo n.º 3
0
def part_2(intcode):
    p2 = 0
    amp_a = IntCodeComputer(intcode)
    amp_b = IntCodeComputer(intcode)
    amp_c = IntCodeComputer(intcode)
    amp_d = IntCodeComputer(intcode)
    amp_e = IntCodeComputer(intcode)
    amps = [amp_a, amp_b, amp_c, amp_d, amp_e]
    for perm in permutations([5, 6, 7, 8, 9]):
        # Setup the amps phase settings
        for amp in amps:
            amp.reset()
        for index, amp in enumerate(amps):
            amp.write(perm[index])
            amp.run()
        amp_a.write(0)
        amp_a.run()
        curr_amp = 1
        output = amp_a.read()[0]
        while amp_e.status != Status.TERMINATED:
            amps[curr_amp].write(output)
            amps[curr_amp].run()
            output = amps[curr_amp].read()[0]
            curr_amp = ((curr_amp + 1) % len(amps))
        if p2 < int(output):
            p2 = int(output)
    return p2
Exemplo n.º 4
0
def run(controller_input, phase_settings):
    input_signal = 0
    for phase_setting in phase_settings:
        computer = IntCodeComputer(program=copy(controller_input),
                                   phase_setting=phase_setting)
        computer.run(input_signal)
        input_signal = computer.value
    return input_signal
Exemplo n.º 5
0
def solve_day_05(input):
    regex = re.compile("-{0,1}\d+")
    f = open(input, "r")
    computer = IntCodeComputer(regex.findall(f.readline()))
    computer.write(1)
    computer.run()
    p1 = computer.read()[-1]
    computer.reset()
    computer.write(5)
    computer.run()
    p2 = computer.read()[0]
    return (p1, p2)
Exemplo n.º 6
0
class Amplifier:

    def __init__(self, stream):
        self.computer = IntCodeComputer(stream)

    def output(self):
        return self.computer.output

    def run(self, input_queue):
        self.computer.input_queue += input_queue
        self.computer.run()

    def reset(self):
        self.computer.reset()
Exemplo n.º 7
0
def part_1(intcode):
    p1 = 0
    computer = IntCodeComputer(intcode)
    for perm in permutations([0, 1, 2, 3, 4]):
        computer.write([perm[0], 0])
        computer.run()
        output = computer.read()[0]
        computer.reset()
        for p in perm[1:]:
            computer.write([p, output])
            computer.run()
            output = computer.read()[0]
            computer.reset()
        if p1 < output:
            p1 = output
    return p1
Exemplo n.º 8
0
def solve_day_19(input):
    regex = re.compile("-{0,1}\d+")
    f = open(input, "r")
    computer = IntCodeComputer(regex.findall(f.readline()))
    size = 50
    p1 = 0
    for x in range(size):
        for y in range(size):
            # I have no clue why I need three inputs, but I do
            computer.write([0, x, y])
            computer.run()
            result = computer.read()[0]
            p1 += result
            computer.reset()
            print(result, end="")
        print()
    return (p1, 0)
Exemplo n.º 9
0
def solve_day_02(input):
    regex = re.compile("\d+")
    f = open(input, "r")
    computer = IntCodeComputer(regex.findall(f.readline()))
    computer.run()
    p1 = computer.memory[0]
    p2 = 0
    has_found = False
    for noun in range(99):
        for verb in range(99):
            computer.reset()
            computer.memory[1] = noun
            computer.memory[2] = verb
            computer.run()
            if computer.memory[0] == 19690720:
                p2 = 100 * noun + verb
                has_found = True
                break
        if has_found:
            break
    return (p1, p2)
Exemplo n.º 10
0
def run_tests():
    computer = IntCodeComputer(ExpandingList([104, 1125899906842624, 99]))
    computer.run(0)
    assert 1125899906842624 == computer.value

    computer = IntCodeComputer(
        ExpandingList([1102, 34915192, 34915192, 7, 4, 7, 99, 0]))
    computer.run(0)
    assert 1219070632396864 == computer.value

    program = [
        109, 1, 204, -1, 1001, 100, 1, 100, 1008, 100, 16, 101, 1006, 101, 0,
        99
    ]
    computer = IntCodeComputer(ExpandingList(program))
    computer.run(input_signal=0)
    assert program == computer.program[:len(program)]
Exemplo n.º 11
0
 def test_negative(self):
     computer = IntCodeComputer(self.regex.findall("1101,100,-1,4,0"))
     computer.run()
     self.assertEqual([1101, 100, -1, 4, 99], computer.memory)
Exemplo n.º 12
0
class TestIntCodeComputer(unittest.TestCase):

    # def setUp(self):
    #     self.computer = IntCodeComputer()

    def test_intcode_load(self):
        self.computer = IntCodeComputer("2,3,0,3,99")
        self.assertListEqual(list(self.computer.memory.values()),
                             [2, 3, 0, 3, 99])

    def test_intcode_opcode_exeption(self):
        self.computer = IntCodeComputer("0,0,99")
        self.assertRaises(IntCodeComputerOpCodeException, self.computer.run)

    def test_intcode_ADD(self):
        self.computer = IntCodeComputer("1,0,0,0,99")
        self.computer.run()
        self.assertListEqual(list(self.computer.memory.values()),
                             [2, 0, 0, 0, 99])

    def test_intcode_MUL(self):
        self.computer = IntCodeComputer("2,3,0,3,99")
        self.computer.run()
        self.assertListEqual(list(self.computer.memory.values()),
                             [2, 3, 0, 6, 99])

    def test_intcode_IN_input_queue(self):
        self.computer = IntCodeComputer("3,0,3,2,99")
        self.computer.input_queue.append(5)
        self.computer.input_queue.append(6)
        self.computer.run()
        self.assertListEqual(list(self.computer.memory.values()),
                             [5, 0, 6, 2, 99])

    def test_intcode_IN_input_queue_empty_exception(self):
        self.computer = IntCodeComputer("3,0,99")
        self.assertRaises(IntCodeComputerInputQueueException,
                          self.computer.run)

    def test_intcode_IN_event_handler_input(self):
        self.computer = IntCodeComputer("3,0,99", is_enable_events=True)
        self.event_handlers = IntcodeComputerTestEventHandler(self.computer)
        self.event_handlers.input = 88
        self.event_handlers.is_test_input_queue_exception = False
        self.computer.run()
        self.assertEqual(self.computer.input, self.event_handlers.input)

    def test_intcode_IN_event_handler_input_queue_empty_exception(self):
        self.computer = IntCodeComputer("3,0,99", is_enable_events=True)
        self.event_handlers = IntcodeComputerTestEventHandler(self.computer)
        self.event_handlers.is_test_input_queue_exception = True
        self.assertRaises(IntCodeComputerInputQueueException,
                          self.computer.run)

    def test_intcode_IN_event_handler_missing_exeption(self):
        self.computer = IntCodeComputer("3,0,99", is_enable_events=True)
        self.assertRaises(IntCodeComputerEventHandlerException,
                          self.computer.run)

    def test_intcode_OUT(self):
        self.computer = IntCodeComputer("104,88,99")
        self.assertEqual(self.computer.run(), 88)

    def test_intcode_OUT_event_handler(self):
        self.computer = IntCodeComputer("104,88,99", is_enable_events=True)
        self.event_handlers = IntcodeComputerTestEventHandler(self.computer)
        self.computer.run()
        self.assertEqual(self.event_handlers.output, 88)

    def test_intcode_OUT_event_handler_missing_exeption(self):
        self.computer = IntCodeComputer("104,88,99", is_enable_events=True)
        self.assertRaises(IntCodeComputerEventHandlerException,
                          self.computer.run)

    def test_intcode_modes(self):  # using day 5 diagnostic test
        self.computer = IntCodeComputer(
            aoc_download.aoc.puzzle_input_file(year=2019, day=5))
        self.computer.input_queue.append(1)
        while not (self.computer.output
                   or self.computer.opcode == Opcode.HALT):
            self.computer.run()
        self.assertEqual(self.computer.output, 6069343)

    def test_intcode_EQ_true(self):
        self.computer = IntCodeComputer("3,9,8,9,10,9,4,9,99,-1,8")
        self.assertEqual(self.computer.run(8), 1)

    def test_intcode_EQ_false(self):
        self.computer = IntCodeComputer("3,9,8,9,10,9,4,9,99,-1,8")
        self.assertEqual(self.computer.run(7), 0)

    def test_intcode_LT_true(self):
        self.computer = IntCodeComputer("3,3,1107,-1,8,3,4,3,99")
        self.assertEqual(self.computer.run(7), 1)

    def test_intcode_LT_false(self):
        self.computer = IntCodeComputer("3,3,1107,-1,8,3,4,3,99")
        self.assertEqual(self.computer.run(8), 0)

    # def test_intcode_JZ_true(self):
    #     self.computer = IntCodeComputer("3,12,6,12,15,1,13,14,13,4,13,99,-1,0,1,9")
    #     self.assertEqual(self.computer.run(0),0)

    def test_intcode_JZ_false(self):
        self.computer = IntCodeComputer(
            "3,12,6,12,15,1,13,14,13,4,13,99,-1,0,1,9")
        self.assertEqual(self.computer.run(10), 1)

    def test_intcode_jumps_test1(self):
        self.computer = IntCodeComputer(
            "3,21,1008,21,8,20,1005,20,22,107,8,21,20,1006,20,31,1106,0,36,98,0,0,1002,21,125,20,4,20,1105,1,46,104,999,1105,1,46,1101,1000,1,20,4,20,1105,1,46,98,99"
        )
        self.assertEqual(self.computer.run(5), 999)

    def test_intcode_jumps_test2(self):
        self.computer = IntCodeComputer(
            "3,21,1008,21,8,20,1005,20,22,107,8,21,20,1006,20,31,1106,0,36,98,0,0,1002,21,125,20,4,20,1105,1,46,104,999,1105,1,46,1101,1000,1,20,4,20,1105,1,46,98,99"
        )
        self.assertEqual(self.computer.run(8), 1000)

    def test_intcode_jumps_test3(self):
        self.computer = IntCodeComputer(
            "3,21,1008,21,8,20,1005,20,22,107,8,21,20,1006,20,31,1106,0,36,98,0,0,1002,21,125,20,4,20,1105,1,46,104,999,1105,1,46,1101,1000,1,20,4,20,1105,1,46,98,99"
        )
        self.assertEqual(self.computer.run(10), 1001)

    def test_intcode_relative_mode(self):
        self.computer = IntCodeComputer(
            "109,1,204,-1,1001,100,1,100,1008,100,16,101,1006,101,0,99",
            is_enable_events=True)
        self.event_handlers = IntcodeComputerTestEventHandler(self.computer)
        self.computer.run()
        self.assertEqual(
            self.event_handlers.output_cache,
            '109,1,204,-1,1001,100,1,100,1008,100,16,101,1006,101,0,99')

    def test_intcode_large_numbers(self):
        self.computer = IntCodeComputer("104,1125899906842624,99")
        self.assertEqual(self.computer.run(), 1125899906842624)
Exemplo n.º 13
0
class ArcadeGame:
    def __init__(self, program, is_play_free=False, is_show_animation=False):

        # indexes of tile types ... the intcode computer output uses these indexes
        self.EMPTY = 0
        self.WALL = 1
        self.BLOCK = 2
        self.PADDLE = 3
        self.BALL = 4

        # intitialize a few vars used later
        self.x = self.y = None
        self.blocks_total = self.score = 0
        self.ball_x = self.paddle_x = 0

        # init the intcode computer and setup event handlers
        self.computer = IntCodeComputer(program, is_enable_events=True)
        self.computer.input_event.listeners += [self.input_handler]
        self.computer.output_event.listeners += [self.output_handler]

        # if playing free (part 2) then set memory location 0 =2
        if is_play_free:
            self.computer.memory[0] = 2

        # if animating (part 2) then get the turtle graphics initialized
        if is_show_animation:
            self.init_window()
        self.is_show_animation = is_show_animation

    def run(self):
        """ Wrapper function to run the intcode computer """
        self.computer.run()

    def input_handler(self):
        """ whenever the intcode computer wants input we give a value to move the paddle to the same x position as the ball """
        # move the paddle toward the ball x value ... -1, 0, +1
        self.computer.input_queue.append((self.ball_x > self.paddle_x) -
                                         (self.ball_x < self.paddle_x))

    def output_handler(self):
        """ whenever the intcode computer gives output, save x (1st output) and y (2nd output) and process the tile (3rd output) """
        output = self.computer.output
        if self.x == None:  # process first output which will be x value
            self.x = output
        elif self.y == None:  # process second output which will be y value
            self.y = output
        # process the tile (or score) which will be the third output
        else:
            if self.x == -1 and self.y == 0:
                self.score = output
                if self.is_show_animation:  # write the score to the screen if animation requested
                    self.score_turtle.clear()
                    self.score_turtle.write(f'Score: {self.score}',
                                            False,
                                            align='left',
                                            font=('Arial', 14, 'normal'))
            else:
                # increment the blocks total it the output is a block
                self.blocks_total += 1 if output == self.BLOCK else 0
                # save the ball x position if the outpult is the ball
                self.ball_x = self.x if output == self.BALL else self.ball_x
                # save the paddle x position if the output is the paddle
                self.paddle_x = self.x if output == self.PADDLE else self.paddle_x
                if self.is_show_animation:
                    # update the window if animation requested
                    self.update_window(output)

            self.x = self.y = None

    def init_window(self):

        # setup the turtle window
        window = turtle.Screen()
        window.bgcolor('black')
        window.title('Arcade Game')

        # make constants for gif filepaths (these gifs are used for turtle graphics shapes)
        EMPTY_GIF = r'.\\media\img_empty.gif'
        WALL_GIF = r'.\\media\img_wall.gif'
        BLOCK_GIF = r'.\\media\img_block.gif'
        PADDLE_GIF = r'.\\media\img_paddle.gif'
        BALL_GIF = r'.\\media\img_ball.gif'

        # register the gifs that will be used as shapes
        #pylint: disable=E1103
        turtle.register_shape(EMPTY_GIF)
        turtle.register_shape(WALL_GIF)
        turtle.register_shape(BLOCK_GIF)
        turtle.register_shape(PADDLE_GIF)
        turtle.register_shape(BALL_GIF)
        # pylint: enable=E1103

        # init the vars that help scale the turtle graphics screen to the co-ordinates we're using
        WIDTH, HEIGHT = 35, 25
        WINDOW_MULTIPLIER = 26
        WINDOW_X_OFFSET = 0 - (WIDTH * WINDOW_MULTIPLIER // 2)
        WINDOW_Y_OFFSET = 0 + (HEIGHT * WINDOW_MULTIPLIER // 2)

        def make_turtle(gif_path=None, is_score=False):
            """ Make a turtle for each tile type using gifs """
            new_turtle = turtle.Turtle()
            new_turtle.hideturtle()
            new_turtle.penup()
            new_turtle.speed(0)
            if is_score:  # score is a special case i.e. is text rather than a shape
                new_turtle.setpos(WINDOW_X_OFFSET,
                                  WINDOW_Y_OFFSET + 1 * WINDOW_MULTIPLIER)
                new_turtle.color('white')
                new_turtle.write('Score: 0',
                                 False,
                                 align='left',
                                 font=('Arial', 14, 'normal'))
            else:  # set the intial positional to be outside the grid
                new_turtle.setpos(WINDOW_X_OFFSET - WINDOW_MULTIPLIER,
                                  WINDOW_Y_OFFSET + WINDOW_MULTIPLIER)
                new_turtle.shape(gif_path)
            return new_turtle

        # make the turtles (graphics) for each tile
        empty_turtle = make_turtle(EMPTY_GIF)
        wall_turtle = make_turtle(WALL_GIF)
        block_turtle = make_turtle(BLOCK_GIF)
        paddle_turtle = make_turtle(PADDLE_GIF)
        ball_turtle = make_turtle(BALL_GIF)
        self.turtles = [
            empty_turtle, wall_turtle, block_turtle, paddle_turtle, ball_turtle
        ]

        # make the score turtle (graphic)
        self.score_turtle = make_turtle(is_score=True)

        # init the dictionaries that will maintain graphics state
        self.grid_stamps = {}
        self.grid_turtles = {}

        # setup up functions for scaling position to screen position
        self.window_x = lambda x: WINDOW_X_OFFSET + (x * WINDOW_MULTIPLIER)
        self.window_y = lambda y: WINDOW_Y_OFFSET - (y * WINDOW_MULTIPLIER)

    def update_window(self, turtle_type):
        """ update the screen coordinate that represents a grid coordinate state """

        if turtle_type == self.EMPTY:
            # get the turtle for this coordinate if exists
            this_turtle = self.grid_turtles.get((self.x, self.y), None)
            if this_turtle:
                # remove the stamp from the window
                this_turtle.clearstamp(self.grid_stamps[(self.x, self.y)])
                # remove the stamp from the dictionary of stamped coordinates
                self.grid_stamps.pop((self.x, self.y), None)
                # remove the turtle that made the stamp
                self.grid_turtles.pop((self.x, self.y), None)
        else:
            # get a reference to the correct turtle
            this_turtle = self.turtles[turtle_type]
            # set the new postion for that turtle
            this_turtle.setpos(self.window_x(self.x), self.window_y(self.y))
            # stamp the window at that position and save the stamp id (required for later removal)
            self.grid_stamps[(self.x, self.y)] = this_turtle.stamp()
            # save a reference to the turtle that made the stamp at that position
            self.grid_turtles[(self.x, self.y)] = this_turtle
Exemplo n.º 14
0
def solve_day_17(input):
    regex = re.compile("-{0,1}\d+")
    f = open(input, "r")
    computer = IntCodeComputer(regex.findall(f.readline()))
    computer.run()
    camera = computer.read()
    lst = []
    line = []
    for c in camera:
        if c == 10:
            lst.append(line)
            line = []
        else:
            line.append(c)
    p1 = 0
    for y, cy in enumerate(lst[1:-2], 1):
        for x, cx in enumerate(cy[1:-1], 1):
            if cx == 35:
                if lst[y - 1][x] == 35 and lst[y + 1][x] == 35 and lst[y][
                        x - 1] == 35 and lst[y][x + 1] == 35:
                    lst[y][x] = ord("O")
                    p1 += x * y
    # This was just for pretty printing so see how things look, but I am now using it
    # to manually solve part 2
    for cy in lst:
        for cx in cy:
            if cx == ord("."):
                print("⬛", end="")
            else:
                print("⬜", end="")
        print()
    # and after a little puzzling we get (see Scaffold.png)
    # "A"=65, "B"=66, "C"=67, ","=44, "\n"=10
    # "L"=76, "R"=82
    # "12"=49 50, "8"=56, "6"=54, "4"=52
    # "n" = 110
    # A = L12,L12,L6,L6
    # B = L12,L6,R12,R8
    # C = R8,R4,L12
    # A,C,A,B,C,A,B,C,A,B
    computer.reset()
    computer.memory[0] = 2
    instructions = [
        #A   ,   C   ,   A   ,   B   ,   C   ,   A   ,   B   ,   C   ,   A   ,   B  \n
        65,
        44,
        67,
        44,
        65,
        44,
        66,
        44,
        67,
        44,
        65,
        44,
        66,
        44,
        67,
        44,
        65,
        44,
        66,
        10,
        #L   ,   1   2   ,   L   ,   1   2   ,   L   ,   6   ,   L   ,   6  \n
        76,
        44,
        49,
        50,
        44,
        76,
        44,
        49,
        50,
        44,
        76,
        44,
        54,
        44,
        76,
        44,
        54,
        10,
        #L   ,   1   2   ,   L   ,   6   ,   R   ,   1   2   ,   R   ,   8  \n
        76,
        44,
        49,
        50,
        44,
        76,
        44,
        54,
        44,
        82,
        44,
        49,
        50,
        44,
        82,
        44,
        56,
        10,
        #R   ,   8   ,   R   ,   4   ,   L   ,   1   2  \n
        82,
        44,
        56,
        44,
        82,
        44,
        52,
        44,
        76,
        44,
        49,
        50,
        10,
        #n,  \n
        110,
        10
    ]
    computer.write(instructions)
    computer.run()
    p2 = computer.read()[-1]
    return (p1, p2)
Exemplo n.º 15
0
class RepairDroid:

    Dir = namedtuple('Dir', ['Forward', 'dy', 'dx', 'Reverse'])

    NORTH, SOUTH, WEST, EAST = 1, 2, 3, 4
    NORTH_DIR = Dir(NORTH, -1, 0, SOUTH)
    SOUTH_DIR = Dir(SOUTH, 1, 0, NORTH)
    WEST_DIR = Dir(WEST, 0, -1, EAST)
    EAST_DIR = Dir(EAST, 0, 1, WEST)
    DIRS = [NORTH_DIR, EAST_DIR, SOUTH_DIR, WEST_DIR]

    START_CHAR = "D"
    PATH_CHAR = " "
    SYSTEM_CHAR = "S"
    WALL_CHAR = "#"
    VISITED_CHAR = "."

    # map locations you can move to (not WALL or already explored)
    OPEN_CHARS = {PATH_CHAR,
                  SYSTEM_CHAR}  # usually PATH, END when solving a maze

    # IntCode Computer responses
    RESPONSE_IS_WALL = 0
    RESPONSE_IS_MOVED = 1
    RESPONSE_IS_SYSTEM = 2

    IS_VISITED = 3  # to use ball for visited path

    def __init__(self, program):
        self.computer = IntCodeComputer(program)
        self.maze = {(0, 0): RepairDroid.START_CHAR}
        self.system = None
        self.init_window()
        self.update_window(2, 0, 0)  #display start
        self.step_count = 0

    def solve_for_system(self, y, x):
        if self.maze[(y, x)] == RepairDroid.SYSTEM_CHAR:
            # base case - endpoint has been found
            return True
        else:
            # search recursively in each direction from here
            for dir in RepairDroid.DIRS:
                ny, nx = y + dir.dy, x + dir.dx
                if self.maze[(
                        ny,
                        nx)] in RepairDroid.OPEN_CHARS:  # can I go this way?
                    if self.maze[(
                            ny, nx
                    )] != RepairDroid.START_CHAR and self.maze[(
                            ny, nx
                    )] != RepairDroid.SYSTEM_CHAR:  # don't overwrite start or end
                        # mark direction chosen
                        self.maze[(y, x)] = RepairDroid.VISITED_CHAR
                        self.update_window(RepairDroid.IS_VISITED, ny, nx)
                    if self.solve_for_system(ny, nx):  # recurse...
                        self.step_count += 1
                        return True  # solution found!

        # no solution found from this location
        if self.maze[(y, x)] != RepairDroid.START_CHAR and self.maze[
            (y, x)] != RepairDroid.SYSTEM_CHAR:  # don't overwrite
            # clear failed search from map
            self.maze[(y, x)] = RepairDroid.PATH_CHAR
            self.update_window(RepairDroid.RESPONSE_IS_MOVED, y, x)
        return False

    def map_out_maze(self, y, x):
        """ uses recursion to map out the maze by supplying input to the intcode computer and reading responses """
        for dir in RepairDroid.DIRS:
            ny, nx = y + dir.dy, x + dir.dx
            response = self.computer.run(dir.Forward)
            if response == RepairDroid.RESPONSE_IS_WALL:
                self.maze[(ny, nx)] = RepairDroid.WALL_CHAR
                self.update_window(response, ny, nx)
            elif ((ny, nx) in self.maze) and self.maze[(
                    ny, nx)] == RepairDroid.VISITED_CHAR:
                self.computer.run(dir.Reverse)
            else:
                if response == RepairDroid.RESPONSE_IS_SYSTEM:
                    self.system = (ny, nx)
                    self.update_window(response, ny, nx)
                self.maze[(ny, nx)] = RepairDroid.VISITED_CHAR
                self.update_window(RepairDroid.IS_VISITED, ny, nx)
                self.map_out_maze(ny, nx)  # recurse...
                self.computer.run(
                    dir.Reverse
                )  # after all directions tested for location, step back

        # no solution found from this location
        if self.maze[(y, x)] != RepairDroid.START_CHAR and self.maze[
            (y, x)] != RepairDroid.SYSTEM_CHAR:  # don't overwrite
            # clear failed search from map
            self.maze[(y, x)] = RepairDroid.PATH_CHAR
            self.update_window(RepairDroid.RESPONSE_IS_MOVED, y, x)
        return False

    def init_window(self):

        # setup the turtle window
        self.window = turtle.Screen()
        self.window.bgcolor('black')
        self.window.title('Repair Droid Maze')
        self.window.setup(width=1.0, height=1.0)  # maximize screen

        # make constants for gif filepaths (these gifs are used for turtle graphics shapes)
        EMPTY_GIF = r'.\\media\img_empty.gif'
        WALL_GIF = r'.\\media\img_wall.gif'
        BLOCK_GIF = r'.\\media\img_block.gif'
        BALL_GIF = r'.\\media\img_ball.gif'

        # register the gifs that will be used as shapes
        #pylint: disable=E1103
        turtle.register_shape(EMPTY_GIF)
        turtle.register_shape(WALL_GIF)
        turtle.register_shape(BLOCK_GIF)
        turtle.register_shape(BALL_GIF)
        # pylint: enable=E1103

        # init the vars that help scale the turtle graphics screen to the co-ordinates we're using
        WINDOW_MULTIPLIER = 24
        # setup up functions for scaling position to screen position
        self.window_x = lambda x: x * WINDOW_MULTIPLIER
        self.window_y = lambda y: -1 * y * WINDOW_MULTIPLIER

        def make_turtle(gif_path=None, is_score=False):
            """ Make a turtle for each tile type using gifs """
            new_turtle = turtle.Turtle()
            new_turtle.hideturtle()
            new_turtle.penup()
            new_turtle.speed(0)
            new_turtle.setpos(0, 0)
            new_turtle.shape(gif_path)
            return new_turtle

        # make the turtles (graphics) for each tile
        empty_turtle = make_turtle(EMPTY_GIF)
        wall_turtle = make_turtle(WALL_GIF)
        block_turtle = make_turtle(BLOCK_GIF)
        ball_turtle = make_turtle(BALL_GIF)
        self.turtles = [wall_turtle, empty_turtle, block_turtle, ball_turtle]

        # init the dictionaries that will maintain graphics state
        self.grid_stamps = {}
        self.grid_turtles = {}

    def update_window(self, turtle_type, y, x):
        """ update the screen coordinate that represents a grid coordinate state """

        if turtle_type == RepairDroid.RESPONSE_IS_MOVED:
            # get the turtle for this coordinate if exists
            this_turtle = self.grid_turtles.get((x, y), None)
            if this_turtle:
                # remove the stamp from the window
                this_turtle.clearstamp(self.grid_stamps[(x, y)])
                # remove the stamp from the dictionary of stamped coordinates
                self.grid_stamps.pop((x, y), None)
                # remove the turtle that made the stamp
                self.grid_turtles.pop((x, y), None)
        else:
            # get a reference to the correct turtle
            this_turtle = self.turtles[turtle_type]
            # set the new postion for that turtle
            this_turtle.setpos(self.window_x(x), self.window_y(y))
            # stamp the window at that position and save the stamp id (required for later removal)
            self.grid_stamps[(x, y)] = this_turtle.stamp()
            # save a reference to the turtle that made the stamp at that position
            self.grid_turtles[(x, y)] = this_turtle
Exemplo n.º 16
0
from intcode_computer import parse_input, IntCodeComputer, ExpandingList


def run_tests():
    computer = IntCodeComputer(ExpandingList([104, 1125899906842624, 99]))
    computer.run(0)
    assert 1125899906842624 == computer.value

    computer = IntCodeComputer(
        ExpandingList([1102, 34915192, 34915192, 7, 4, 7, 99, 0]))
    computer.run(0)
    assert 1219070632396864 == computer.value

    program = [
        109, 1, 204, -1, 1001, 100, 1, 100, 1008, 100, 16, 101, 1006, 101, 0,
        99
    ]
    computer = IntCodeComputer(ExpandingList(program))
    computer.run(input_signal=0)
    assert program == computer.program[:len(program)]


if __name__ == "__main__":
    # run_tests()

    controller_input = parse_input("day9/input.txt")
    computer = IntCodeComputer(ExpandingList(controller_input))
    computer.verbose = True
    computer.run(input_signal=10)
    print(computer.value)
Exemplo n.º 17
0
 def test_modes(self):
     computer = IntCodeComputer(self.regex.findall("1002,4,3,4,33"))
     computer.run()
     self.assertEqual([1002, 4, 3, 4, 99], computer.memory)
Exemplo n.º 18
0
 def test_reset(self):
     computer = IntCodeComputer(self.regex.findall("1,1,1,4,99,5,6,0,99"))
     computer.run()
     computer.reset()
     self.assertEqual([1, 1, 1, 4, 99, 5, 6, 0, 99], computer.memory)
Exemplo n.º 19
0
 def test_addition_multiplication(self):
     computer = IntCodeComputer(self.regex.findall("1,1,1,4,99,5,6,0,99"))
     computer.run()
     self.assertEqual([30, 1, 1, 4, 2, 5, 6, 0, 99], computer.memory)
Exemplo n.º 20
0
 def test_large_multiplication(self):
     computer = IntCodeComputer(self.regex.findall("2,4,4,5,99,0"))
     computer.run()
     self.assertEqual([2, 4, 4, 5, 99, 9801], computer.memory)
Exemplo n.º 21
0
 def test_multiplication(self):
     computer = IntCodeComputer(self.regex.findall("2,3,0,3,99"))
     computer.run()
     self.assertEqual([2, 3, 0, 6, 99], computer.memory)
Exemplo n.º 22
0
import aoc_download
from intcode_computer import IntCodeComputer
YEAR = 2019
DAY = 9

puzzle_input = aoc_download.aoc.puzzle_input_file(YEAR, DAY)

computer = IntCodeComputer(puzzle_input)
computer.input_queue.append(1)
computer.run()

print("part 1:", computer.output)

computer.reset()
computer.input_queue.append(2)
computer.run()

print("part 2:", computer.output)
Exemplo n.º 23
0
 def test_addition(self):
     computer = IntCodeComputer(self.regex.findall("1,0,0,0,99"))
     computer.run()
     self.assertEqual([2, 0, 0, 0, 99], computer.memory)