コード例 #1
0
 def __init__(self, file_name):
     self.computer = Intcode(file_name)
     self._do_not_take = [
         "escape pod",  # "You're launched into space! Bye!"
         "giant electromagnet",  # "The giant electromagnet is stuck to you.  You can't move!!"
         "infinite loop",  # Literally halts the program in an infinite loop
         "molten lava",  # "The molten lava is way too hot! You melt!"
         "photons",  # "It is suddenly completely dark! You are eaten by a Grue!"
         "mug",  # Too heavy, by itself
         "prime number",  # Too heavy, by itself
         "weather machine",  # Too heavy, by itself
         "festive hat",  # Don't take this and our weight is correct with other items
     ]
コード例 #2
0
ファイル: d2.py プロジェクト: Jnesselr/AdventOfCode
class Y2019D2(object):
    def __init__(self, file_name):
        self.computer = Intcode(file_name)

    def part1(self):
        self.computer.reset()
        self.computer.ram[1] = 12
        self.computer.ram[2] = 2
        self.computer.run()

        print("Part 1:", self.computer.ram[0])

    def part2(self):
        result = 0
        for noun in range(100):
            for verb in range(100):
                self.computer.reset()
                self.computer.ram[1] = noun
                self.computer.ram[2] = verb
                self.computer.run()

                if self.computer.ram[0] == 19690720:
                    result = 100 * noun + verb
                    break

        print("Part 2:", result)
コード例 #3
0
ファイル: d23.py プロジェクト: Jnesselr/AdventOfCode
    def __init__(self, file_name):
        self.NICs: Dict[int, Intcode] = {}
        self.queues: Dict[int, Queue] = {}
        for i in range(50):
            self.NICs[i] = Intcode(file_name)
            self.queues[i] = Queue()

        self.queues[255] = Queue()
コード例 #4
0
ファイル: d11.py プロジェクト: Jnesselr/AdventOfCode
class Y2019D11(object):
    def __init__(self, file_name):
        self.robot = Intcode(file_name)
        self.grid = InfiniteGrid[bool]()  # False -> black; True -> white

    def _paint(self):
        self.robot.reset()
        self.robot.run()

        turtle = Turtle(direction=TurtleDirection.UP)
        painted_tiles = set()
        while not self.robot.halted:
            if turtle.coordinate not in self.grid:
                tile_is_white = False
            else:
                tile_is_white = self.grid[turtle.coordinate]

            self.robot.input(1 if tile_is_white else 0)

            new_color = self.robot.output()

            # Paint the current tile white or black
            self.grid[turtle.coordinate] = True if new_color == 1 else False
            painted_tiles.add(turtle.coordinate)

            turn = self.robot.output()

            if turn == 0:
                turtle = turtle.turn_left()
            else:
                turtle = turtle.turn_right()

            turtle = turtle.forward()

        return painted_tiles

    def part1(self):
        self.grid.clear()
        painted_tiles = self._paint()
        result = len(painted_tiles)

        print("Part 1:", result)

    def part2(self):
        self.grid.clear()
        self.grid[Coordinate(0, 0)] = True
        self._paint()

        print("Part 2:")
        self.grid.to_grid().print(key=lambda is_white: '#' if is_white else ' ')
コード例 #5
0
class Y2019D21(object):
    def __init__(self, file_name):
        self.computer = Intcode(file_name)

    def part1(self):
        result = self._run("NOT A J\n"
                           "NOT B T\n"
                           "OR T J\n"
                           "NOT C T\n"
                           "OR T J\n"
                           "AND D J\n"
                           "WALK\n")

        print("Part 1:", result)

    def part2(self):
        result = self._run("NOT H T\n"
                           "OR C T\n"
                           "AND B T\n"
                           "AND A T\n"
                           "NOT T J\n"
                           "AND D J\n"
                           "RUN\n")

        print("Part 2:", result)

    def _run(self, *program: str):
        self.computer.reset()
        self.computer.run()
        self.computer.output_str()
        for command in program:
            self.computer.input_str(command)

        result = self.computer.output_str()

        if "Didn't make it across" in result:
            print(result)
            return -1
        else:
            return self.computer.output()
コード例 #6
0
ファイル: d19.py プロジェクト: Jnesselr/AdventOfCode
 def __init__(self, file_name):
     self.drone = Intcode(file_name)
コード例 #7
0
class Y2019D5(object):
    def __init__(self, file_name):
        self.computer = Intcode(file_name)

    def part1(self):
        self.computer.reset()
        self.computer.run()
        self.computer.input(1)

        outputs = []
        while not self.computer.halted:
            if self.computer.has_output:
                output = self.computer.output()
                outputs.append(output)

        is_valid_output = len(list(filter(None,
                                          outputs))) == 1 and outputs[-1] > 0

        if is_valid_output:
            print("Part 1:", outputs[-1])
        else:
            print("INVALID!")
            for output in outputs:
                print(output)

    def part2(self):
        self.computer.reset()
        self.computer.run()
        self.computer.input(5)
        result = self.computer.output()

        print("Part 2:", result)
コード例 #8
0
ファイル: d7.py プロジェクト: Jnesselr/AdventOfCode
 def __init__(self, file_name):
     self.comp_a = Intcode(file_name)
     self.comp_b = Intcode(file_name)
     self.comp_c = Intcode(file_name)
     self.comp_d = Intcode(file_name)
     self.comp_e = Intcode(file_name)
コード例 #9
0
ファイル: d7.py プロジェクト: Jnesselr/AdventOfCode
class Y2019D7(object):
    def __init__(self, file_name):
        self.comp_a = Intcode(file_name)
        self.comp_b = Intcode(file_name)
        self.comp_c = Intcode(file_name)
        self.comp_d = Intcode(file_name)
        self.comp_e = Intcode(file_name)

    @staticmethod
    def _iterator(start, end):
        for a in range(start, end + 1):
            for b in range(start, end + 1):
                for c in range(start, end + 1):
                    for d in range(start, end + 1):
                        for e in range(start, end + 1):
                            if len({a, b, c, d, e}) == 5:
                                yield [a, b, c, d, e]

    def _reset_and_start_computers(self):
        self.comp_a.reset()
        self.comp_a.run()
        self.comp_b.reset()
        self.comp_b.run()
        self.comp_c.reset()
        self.comp_c.run()
        self.comp_d.reset()
        self.comp_d.run()
        self.comp_e.reset()
        self.comp_e.run()

    def part1(self):
        result = 0

        for settings in self._iterator(0, 4):
            self._reset_and_start_computers()

            self.comp_a.input(settings[0])
            self.comp_b.input(settings[1])
            self.comp_c.input(settings[2])
            self.comp_d.input(settings[3])
            self.comp_e.input(settings[4])

            self.comp_a.input(0)
            self.comp_b.input(self.comp_a.output())
            self.comp_c.input(self.comp_b.output())
            self.comp_d.input(self.comp_c.output())
            self.comp_e.input(self.comp_d.output())

            result = max(result, self.comp_e.output())

        print("Part 1:", result)

    def part2(self):
        result = 0

        for settings in self._iterator(5, 9):
            self._reset_and_start_computers()

            self.comp_a.input(settings[0])
            self.comp_b.input(settings[1])
            self.comp_c.input(settings[2])
            self.comp_d.input(settings[3])
            self.comp_e.input(settings[4])

            self.comp_a.input(0)

            while not self.comp_a.halted:
                self.comp_b.input(self.comp_a.output())
                self.comp_c.input(self.comp_b.output())
                self.comp_d.input(self.comp_c.output())
                self.comp_e.input(self.comp_d.output())

                if not self.comp_a.halted:
                    self.comp_a.input(self.comp_e.output())

            result = max(result, self.comp_e.output())

        print("Part 2:", result)
コード例 #10
0
 def __init__(self, file_name):
     self.arcade = Intcode(file_name)
     self.grid: InfiniteGrid[Tile] = InfiniteGrid[Tile]()
     self.score = 0
コード例 #11
0
class Y2019D13(object):
    def __init__(self, file_name):
        self.arcade = Intcode(file_name)
        self.grid: InfiniteGrid[Tile] = InfiniteGrid[Tile]()
        self.score = 0

    def reset(self):
        self.score = 0
        self.grid.clear()
        self.arcade.reset()

    def _get_game_update(self):
        while self.arcade.has_output:
            x = self.arcade.output()
            y = self.arcade.output()
            tile_id = self.arcade.output()

            if x == -1 and y == 0:
                self.score = tile_id
            else:
                self.grid[x, y] = Tile.from_id(tile_id)

        # self.grid.to_grid().print(key=lambda x: x.character)

    def part1(self):
        self.reset()
        self.arcade.run()
        self._get_game_update()
        result = len(self.grid.find(Tile.BLOCK))

        print("Part 1:", result)

    def part2(self):
        self.reset()
        self.arcade.ram[0] = 2
        self.arcade.run()
        self._get_game_update()

        while not self.arcade.halted:
            ball = self.grid.find(Tile.BALL)[0]
            paddle = self.grid.find(Tile.PADDLE)[0]
            # Move the paddle if needed

            if ball.x > paddle.x:
                self.arcade.input(1)
            elif ball.x < paddle.x:
                self.arcade.input(-1)
            else:
                self.arcade.input(0)

            self._get_game_update()

        print("Part 2:", self.score)
コード例 #12
0
 def __init__(self, file_name):
     self.droid = Intcode(file_name)
     self.grid = InfiniteGrid[Tile]()
コード例 #13
0
ファイル: d2.py プロジェクト: Jnesselr/AdventOfCode
 def __init__(self, file_name):
     self.computer = Intcode(file_name)
コード例 #14
0
ファイル: d19.py プロジェクト: Jnesselr/AdventOfCode
class Y2019D19(object):
    def __init__(self, file_name):
        self.drone = Intcode(file_name)

    def _is_beam(self, x: int, y: int):
        if x < 0 or y < 0:
            return False

        self.drone.reset()
        self.drone.run()
        self.drone.input(x)
        self.drone.input(y)
        return self.drone.output() == 1

    def part1(self):
        result = 0
        for x in range(50):
            for y in range(50):
                if self._is_beam(x, y):
                    result += 1

        print("Part 1:", result)

    def part2(self):
        square_side = 100
        end_cache = {}

        def valid_y(y):
            # Bit of a hack, but the beam isn't continuous
            if y < 10:
                return False

            if y in end_cache:
                end_x = end_cache[y]
            else:
                start_search = BinarySearch(lambda x: self._is_beam(x, y))
                start_x = start_search.earliest(0, lambda x: x + 1)
                end_x = start_search.latest(start_x, lambda x: x * 2)
                end_cache[y] = end_x

            test_x = end_x - square_side + 1
            test_y = y + square_side - 1
            beam = self._is_beam(test_x, test_y)
            return beam

        search = BinarySearch(valid_y)
        found_y = search.earliest(1, lambda x: x * 2)
        found_x = end_cache[found_y] - square_side + 1
        result = found_x * 10000 + found_y

        print("Part 2:", result)

    def _find_beam_right(self, start_x: int, y: int, max_search_x=10000):
        seen_beam = False
        for x in range(start_x, max_search_x):
            is_beam = self._is_beam(x, y)
            if not is_beam and seen_beam:
                return x - 1

            if is_beam:
                seen_beam = True
        return None
コード例 #15
0
class Y2019D9(object):
    def __init__(self, file_name):
        self.computer = Intcode(file_name)

    def part1(self):
        self.computer.reset()
        self.computer.run()
        self.computer.input(1)

        outputs = []
        while not self.computer.halted:
            outputs.append(self.computer.output())

        if len(outputs) == 1:
            print("Part 1:", outputs[-1])
        else:
            print("Something went wrong, invalid output:")
            for output in outputs:
                print(output)

    def part2(self):
        self.computer.reset()
        self.computer.run()
        self.computer.input(2)

        print("Part 2:", self.computer.output())
コード例 #16
0
ファイル: d11.py プロジェクト: Jnesselr/AdventOfCode
 def __init__(self, file_name):
     self.robot = Intcode(file_name)
     self.grid = InfiniteGrid[bool]()  # False -> black; True -> white
コード例 #17
0
ファイル: d17.py プロジェクト: Jnesselr/AdventOfCode
class Y2019D17(object):
    def __init__(self, file_name):
        self.computer = Intcode(file_name)

    def part1(self):
        self.computer.reset()
        self.computer.run()
        map_string = self.computer.output_str()
        grid = Grid.from_str(map_string)

        result = 0
        scaffolding = grid.find('#')

        for scaffold in scaffolding:
            intersecting = all(grid[neighbor] == '#'
                               for neighbor in scaffold.neighbors())

            if intersecting:
                result += scaffold.x * scaffold.y

        print("Part 1:", result)

    def part2(self):
        self.computer.reset()
        self.computer.ram[0] = 2
        self.computer.run()

        self.computer.output_str()
        self.computer.input_str("B,C,B,C,A,B,C,A,B,A\n")
        self.computer.output_str()
        self.computer.input_str("R,6,L,8,L,10,R,6\n")
        self.computer.output_str()
        self.computer.input_str("R,6,L,6,L,10\n")
        self.computer.output_str()
        self.computer.input_str("L,8,L,6,L,10,L,6\n")
        self.computer.output_str()
        self.computer.input_str("n\n")
        map_string = self.computer.output_str()
        grid = Grid.from_str(map_string)
        result = self.computer.output()

        print("Part 2:", result)
コード例 #18
0
class Y2019D15(object):
    def __init__(self, file_name):
        self.droid = Intcode(file_name)
        self.grid = InfiniteGrid[Tile]()

    def _map_out_grid(self):
        self.grid.clear()
        self.droid.reset()

        all_directions = [
            TurtleDirection.NORTH, TurtleDirection.SOUTH, TurtleDirection.EAST,
            TurtleDirection.WEST
        ]

        droid_coordinate = Coordinate(0, 0)
        self.grid[droid_coordinate] = Tile.EMPTY
        backtrack = []
        need_to_check = {droid_coordinate: all_directions.copy()}

        self.droid.run()
        while backtrack or need_to_check:
            test_directions = need_to_check[droid_coordinate]

            # Nowhere to move, try to go back
            if not test_directions:
                del need_to_check[droid_coordinate]
                if backtrack:
                    back = backtrack.pop()
                    self.droid.input(self._get_move_input(back))
                    self.droid.output(
                    )  # Read an output, although we know we can move back
                    droid_coordinate = back.move(droid_coordinate)
                continue

            direction = test_directions.pop()
            if backtrack and direction == backtrack[-1]:
                continue  # Don't go back, use backtrack stack for that

            self.droid.input(self._get_move_input(direction))
            output = self.droid.output()

            next_coordinate = direction.move(droid_coordinate)
            self.grid[next_coordinate] = Tile.from_id(output)
            if output != 0:
                droid_coordinate = next_coordinate
                backtrack.append(direction.opposite())
                need_to_check[droid_coordinate] = all_directions.copy()

    def _get_move_input(self, direction: TurtleDirection):
        if direction == TurtleDirection.NORTH:
            return 1
        elif direction == TurtleDirection.SOUTH:
            return 2
        elif direction == TurtleDirection.WEST:
            return 3
        elif direction == TurtleDirection.EAST:
            return 4

    def part1(self):
        self._map_out_grid()

        start = Coordinate(0, 0)
        oxygen = self.grid.find(Tile.OXYGEN)[0]
        graph = self.grid.to_graph(Tile.EMPTY, Tile.OXYGEN)
        # -1 is because path includes start and they want "steps to oxygen"
        result = len(graph.find_path(start, oxygen, CoordinateHeuristic())) - 1

        print("Part 1:", result)

    def part2(self):
        self._map_out_grid()

        empty_tiles = self.grid.find(Tile.EMPTY)

        minutes = 0
        while empty_tiles:
            oxygen = self.grid.find(Tile.OXYGEN)
            for oxygen_space in oxygen:
                for neighbor in oxygen_space.neighbors():
                    if self.grid[neighbor] == Tile.EMPTY:
                        self.grid[neighbor] = Tile.OXYGEN

            minutes += 1
            empty_tiles = self.grid.find(Tile.EMPTY)

        print("Part 2:", minutes)
コード例 #19
0
class Y2019D25(object):
    def __init__(self, file_name):
        self.computer = Intcode(file_name)
        self._do_not_take = [
            "escape pod",  # "You're launched into space! Bye!"
            "giant electromagnet",  # "The giant electromagnet is stuck to you.  You can't move!!"
            "infinite loop",  # Literally halts the program in an infinite loop
            "molten lava",  # "The molten lava is way too hot! You melt!"
            "photons",  # "It is suddenly completely dark! You are eaten by a Grue!"
            "mug",  # Too heavy, by itself
            "prime number",  # Too heavy, by itself
            "weather machine",  # Too heavy, by itself
            "festive hat",  # Don't take this and our weight is correct with other items
        ]

    def part1(self):
        self.computer.reset()
        self.computer.run()

        back_moves: List[str] = []
        path_from_security: Optional[List[str]] = None
        seen: Set[Tuple[str, str]] = set()
        taken: Set[str] = set()

        while True:
            output = self.computer.output_str()
            # print(output)
            location = DungeonLocation.read(output)

            if location.name == "Security Checkpoint":
                path_from_security = back_moves.copy()
                previous_move = back_moves.pop()
                # print(f"Going back {previous_move}")
                self.computer.input_str(f"{previous_move}\n")
                continue

            for item in location.items:
                if item not in self._do_not_take:
                    taken.add(item)
                    input_str = f"take {item}\n"
                    # print(input_str)
                    self.computer.input_str(input_str)
                    response = self.computer.output_str()
                    # print(response)

            moved_through_a_door = False
            opposite_direction = None
            for direction in location.doors_here_lead:
                back_direction = back_moves[-1] if len(
                    back_moves) > 0 else None
                if back_direction == direction:
                    continue

                movement = (location.name, direction)
                if movement in seen:
                    continue

                if direction == "north":
                    opposite_direction = "south"
                elif direction == "south":
                    opposite_direction = "north"
                elif direction == "east":
                    opposite_direction = "west"
                elif direction == "west":
                    opposite_direction = "east"

                seen.add(movement)
                back_moves.append(opposite_direction)
                moved_through_a_door = True

                # print(f"Going {direction}")
                self.computer.input_str(f"{direction}\n")

                break

            if not moved_through_a_door:
                if len(back_moves) > 0:
                    previous_move = back_moves.pop()
                    # print(f"Going back {previous_move}")
                    self.computer.input_str(f"{previous_move}\n")
                else:
                    break

        for movement in path_from_security:
            if movement == "north":
                movement = "south"
            elif movement == "south":
                movement = "north"
            elif movement == "east":
                movement = "west"
            elif movement == "west":
                movement = "east"

            self.computer.input_str(f"{movement}\n")
            self.computer.output_str()

        self.computer.input_str("east\n")
        output = self.computer.output_str()
        result = re.search(r"(\d+)", output).group(1)

        print("Part 1:", result)

    def part2(self):
        pass