diff --git a/aoc2024/src/day15/__init__.py b/aoc2024/src/day15/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/aoc2024/src/day15/python/__init__.py b/aoc2024/src/day15/python/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/aoc2024/src/day15/python/solution.py b/aoc2024/src/day15/python/solution.py new file mode 100644 index 0000000..05510a7 --- /dev/null +++ b/aoc2024/src/day15/python/solution.py @@ -0,0 +1,150 @@ +# Copyright 2024 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +from typing import Sequence + +type WarehouseMap = Sequence[Sequence[str]] +type Position = tuple[int, int] # (x,y) +type Direction = tuple[int, int] # (x,y) +_ROBOT = '@' +_BOX = 'O' +_WALL = '#' +_EMPTY = '.' + + +def _opposite_dir(dir: Direction) -> Direction: + inverse = { + (0, 1): (0, -1), + (0, -1): (0, 1), + (-1, 0): (1, 0), + (1, 0): (-1, 0), + } + return inverse.get(dir) + + +class Warehouse: + def __init__(self, warehouse_map: WarehouseMap, robot_moves: Sequence[Position]): + self._warehouse_map: list[list[str]] = [list(line) for line in warehouse_map] + self._width = len(self._warehouse_map[0]) + self._height = len(self._warehouse_map) + self._robot_pos = self._find_robot_pos() + self._robot_moves = robot_moves + self._next_move_index = 0 + + def simulate(self) -> None: + """Simulates all robot moves in the warehouse.""" + while self._next_move_index < len(self._robot_moves): + self._move_robot() + self._next_move_index += 1 + + def sum_all_boxes_gps_coordinates(self) -> int: + """Returns the sum of all the boxes' GPS coordinates. + A box GPS coordinate is 100 times its distance from the top edge of the + warehouse plus its distance from the left edge of the map. + """ + result = 0 + for y in range(self._height): + for x in range(self._width): + if self._charAt(pos=(x, y)) == _BOX: + result += 100 * y + x + return result + + def _find_robot_pos(self) -> Position: + """Returns the position of the robot.""" + for y in range(self._height): + for x in range(self._width): + if self._warehouse_map[y][x] == _ROBOT: + return x, y + raise ValueError('Robot not found!') + + def _charAt(self, pos: Position) -> str: + """Returns what element is on the warehouse at a given position.""" + return self._warehouse_map[pos[1]][pos[0]] + + def _update(self, pos: Position, value: str) -> None: + """Updates a warehouse position with a given element.""" + self._warehouse_map[pos[1]][pos[0]] = value + + def _move_robot(self) -> None: + """Attempts to move robot one step. If the robot cannot move, it is a NOP.""" + next_move = self._robot_moves[self._next_move_index] + next_pos = (self._robot_pos[0] + next_move[0], self._robot_pos[1] + next_move[1]) + if self._charAt(next_pos) == _EMPTY: + self._update(self._robot_pos, _EMPTY) + self._robot_pos = next_pos + self._update(self._robot_pos, _ROBOT) + elif self._charAt(next_pos) == _BOX: + self._push(pos=next_pos, dir=next_move) + if self._charAt(next_pos) == _EMPTY: + self._update(self._robot_pos, _EMPTY) + self._robot_pos = next_pos + self._update(self._robot_pos, _ROBOT) + + def _within_bounds(self, pos: Position): + """Returns true if a position is within warehouse bounds.""" + return 0 <= pos[0] < self._width and 0 <= pos[1] < self._height + + def _find_next_empty_pos(self, pos: Position, dir: Direction) -> Position | None: + """Returns the next empty space from a position towards a given direction.""" + while self._within_bounds(pos): + if self._charAt(pos) == _WALL: + return None # We hit a wall before an empty space. + if self._charAt(pos) == _EMPTY: + return pos + pos = (pos[0] + dir[0], pos[1] + dir[1]) + # Empty space was not found. + return None + + def _push(self, pos: Position, dir: Direction) -> None: + """Attempts to push boxes from given position towards given direction. + If there is no space to move boxes, it is a NOP.""" + next_empty_pos = self._find_next_empty_pos(pos, dir) + if next_empty_pos is not None: + next_pos = next_empty_pos + while next_pos != pos: + self._update(next_pos, _BOX) + opposite_dir = _opposite_dir(dir) + next_pos = (next_pos[0] + opposite_dir[0], next_pos[1] + opposite_dir[1]) + self._update(pos, _EMPTY) + + +def _parse(input: Sequence[str]) -> tuple[WarehouseMap, Sequence[Position]]: + """Parses the input and returns the warehouse map and sequence of robot moves.""" + is_map = True + warehouse_map = [] + robot_moves = [] + for line in input: + if line == '': + is_map = False + if is_map: + warehouse_map.append(line) + else: + for i in line: + if i == '^': # Up. + robot_moves.append((0, -1)) + if i == '<': # Left. + robot_moves.append((-1, 0)) + if i == '>': # Right. + robot_moves.append((1, 0)) + if i == 'v': # Down. + robot_moves.append((0, 1)) + return tuple(warehouse_map), tuple(robot_moves) + + +def sum_all_boxes_gps_coordinates(input: Sequence[str]) -> int: + """Simulates all the robot moves in the warehouse and returns the sum of + all boxes GPS coordinates at the end state.""" + warehouse_map, robot_moves = _parse(input) + warehouse = Warehouse(warehouse_map, robot_moves) + warehouse.simulate() + return warehouse.sum_all_boxes_gps_coordinates() diff --git a/aoc2024/test/day15/__init__.py b/aoc2024/test/day15/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/aoc2024/test/day15/python/__init__.py b/aoc2024/test/day15/python/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/aoc2024/test/day15/python/example1.txt b/aoc2024/test/day15/python/example1.txt new file mode 100644 index 0000000..c6138ff --- /dev/null +++ b/aoc2024/test/day15/python/example1.txt @@ -0,0 +1,10 @@ +######## +#..O.O.# +##@.O..# +#...O..# +#.#.O..# +#...O..# +#......# +######## + +<^^>>>vv>v<< \ No newline at end of file diff --git a/aoc2024/test/day15/python/example2.txt b/aoc2024/test/day15/python/example2.txt new file mode 100644 index 0000000..b2bce78 --- /dev/null +++ b/aoc2024/test/day15/python/example2.txt @@ -0,0 +1,21 @@ +########## +#..O..O.O# +#......O.# +#.OO..O.O# +#..O@..O.# +#O#..O...# +#O..O..O.# +#.OO.O.OO# +#....O...# +########## + +^v>^vv^v>v<>v^v<<><>>v^v^>^<<<><^ +vvv<<^>^v^^><<>>><>^<<><^vv^^<>vvv<>><^^v>^>vv<>v<<<^<^^>>>^<>vv>v^v^<>><>>>><^^>vv>v<^^^>>v^v^<^^>v^^>v^<^v>v<>>v^v^v^^<^^vv< +<>^^^^>>>v^<>vvv^>^^^vv^^>v<^^^^v<>^>vvvv><>>v^<<^^^^^ +^><^><>>><>^^<<^^v>>><^^>v>>>^v><>^v><<<>vvvv>^<><<>^>< +^>><>^v<><^vvv<^^<><^v<<<><<<^^<^>>^<<<^>>^v^>>^v>vv>^<<^v<>><<><<>v<^vv<<<>^^v^>^^>>><<^v>>v^v><^^>>^<>vv^ +<><^^>^^^<>^vv<<^><<><<><<<^^<<<^<<>><<><^^^>^^<>^>v<> +^^>vv<^v^v^<>^^^>>>^^vvv^>vvv<>>>^<^>>>>>^<<^v>^vvv<>^<>< +v^^>>><<^^<>>^v^v^<<>^<^v^v><^<<<><<^vv>>v>v^<<^ \ No newline at end of file diff --git a/aoc2024/test/day15/python/input.txt b/aoc2024/test/day15/python/input.txt new file mode 100644 index 0000000..38a0895 --- /dev/null +++ b/aoc2024/test/day15/python/input.txt @@ -0,0 +1,71 @@ +################################################## +#...O....OO.#O......#...#........#..O..OO.......O# +#.OO#....#.#O..#O.......OO..O.O.O.O.OO..##..OO...# +#O....#O.........O.O.OOO.O..#..OO.O...O..........# +#........O...OO..O..OOO..O.O##...O.O...O..OO.O...# +#...#.#...#.#.O..O.....#...O..OO.O..O....O#..O...# +#.O#.O....O..O.#.....O..O........O.O........O..OO# +#..OO#O..O..##.......O...#...O....O.....O.O...#.O# +#....O...O......O#.O......O......O...O.....OO...## +#.O#.#O.O..O.#.OO........O......#.O.....O..O.#...# +#.O.OOO.......OOO.O.OOO.O.#....O..#....O....O..O.# +#OO.O.....#.#......OO.OO.O.O.#..#..O..#.....##..O# +#...#.O.....OO..O...O...OO.....#..O...#...O....O.# +#.O.O.O............OO.OO#..OO.#.O..#..OOO....O...# +#......#.O.O..#.#O....OO.......OO.O...OO.OO......# +#..O......#O...O.O.#..O.O........O......O...#....# +##O.O#.O#...O...OO..O......................O.....# +#OO....#..OO#O..O..OO.O......O.O..#...O..O...O..## +#.OOO..O...OO...O..OO#..OO#........O.##..O..#O.O.# +#..O..O.OO#...O...#O....O..O.......O..#.#.OO.OO..# +#O.O.O.OOO..#...#..O#O.O...#O#...O.O.O#O.OO.O..O.# +#O#.#........OO...#..#O#.O..#O.OO....OO..O#.OO.O.# +#O..OO..OOOO......O#..O.O#.......O.#O....O.....O.# +#OO..O#..O#....#O.....O....OO..O.O.O.#...#.##....# +#.....O.OO...O..O.......@....O...O..OO....O..#..## +#..O..#..................#............O.#..O.#O..# +#...O...O.OO.O..#..OO..O....O.O..OO.OO#..O....#.## +#.OO.O#.O...O..##..#..O...O.....OO#..#.O.O...OO..# +#OOO.OO..#OO...OOOO...OO...........#...#.O#..##..# +#.O...........OOO....O..O..#...O......O.O......OO# +#O.O..O.OOO#O.......#..O.O.O.OO...O...O..O#O.OO.## +#..OO.....O.O...#....O....OO.....#......#.O#OO##.# +#.O.OOO.O.O.#....O.#O.O.........O.#....OO...O..### +#O...O#O.....#.#O....O.....#...#O..O.OO..O....O..# +#.OO.O..#....#..O......O..#..........OO..O.O..OOO# +#O....O..O........O.#.O..........O...O...OOO#...O# +##O..#.....OO..OO...OO.......O..OO.OO.....#.#..O.# +#O..OO#O...#O..O....#.#.O.O............O..#......# +#....O.#.O.O...O...O.OO......#..O...#.........O#.# +#OO..O...OO.OOOO...OOO.O..OO.......O.O.OO..O.O.O.# +#......O....O##....OO.O.....#.#....OO#.OO........# +#...#.O.#.#....O.........#O.O....O#.O...O..#.O..O# +#O.#.O....O.........O.OO.#......O#..O#O.O....O.OO# +#..OO#.......O..........O..#.O..........O..#.OO..# +#..........#..OO.O#.........O...O....O#......#O..# +#.O.#.#.O.OO.O.O.OO...O..#O.O.O...O.........O###.# +#.OO.#.....#O.....O.OO......O..........OO#...O...# +##....O#.....O.....O....O.....O.O..O........O..#O# +#O.O..O#...O..OO..O.OO.O..O...O.......O..O.O.O...# +################################################## + +>>>>>>>>>^<^>><>^^v<>^v<^<^<^v<<><<<>><><<<<>^^vv^<<><<>^^<^v^>v>><^>>vvv<<>^^<^^^>>^><v^v<^<^^<>>^vv^>^>><>>>vv>^^^>v^v<<>^<v>>>>v<>v<<^>v>v>^v<><<<><^^v><>v>v>^<^^<^v>>^vv^^^<>^<^v^v<^v^><>>>v>^><^v>v^>^>^>>v^vv^^<>^>vv>>^<^<^v^><<>^vvv<^v<^v^<^^>>^><>v^v^<^v^<<<^^^v>v^^>vv>v<^>v<^v>v>v>^<^v<^v^^>><>>>vv^^>v>^^>vv<^v<>v^v>^<^>vvv^>v<^>><>vv<>>^<^v<^^v^>v><<<^^>v^>>v^<<<^^^vv^<^>>^>>^^^><^v^^^^^vv<^<^>v^>^^vv>^><^<<>>^>^^>>><>^>>v>><>>v^>^<>v>>^<><>^^v>^<v<<^<>><><^v^vv>^v^v<^v^<^^>>v^^^>>v<<><^^v>v^<^^<<^^<<<^v^>^^>vvv^>v^^^<<>^vv<<^>v^<><<<>v^<^^v><^v^<><^v^v>^<<<^v^<^^<^<<<<^<^>>>^v^^^v^v^^v^^<>^^^^><>^<^><^v^v<<^>^<^><><^v^<^^vvv>>^>^^^^v^>^^<^v<<<>><^v^^^v^^v<<^^v<><<>v>>^<>v>^<v^<<>><>^<^>v^^>v><^>< +^>>^>v>^>v>^^><>>^><^^^>v<^<>><^>v<vv<^^^v^>^>v><<><<^>v<>v^^v>v^>v^>>^^>v>^<^v>v<^<<^<^v<>v<>><><^vv<>>^v^^v>>>>>v^vv<^^v^v<<^<^^^^<>^^<^>^^^<^vv<>v^>vvv^>v>v^v^<<<^^v>^>>vv>v^<^>^v<^><<<^^vv><>><^v>><<^^v<^v<>v^v^^><<>^v<<<^^<>>^v^>><^v>v^v<>><>^vvv>>^v<<>^>>><<^<>>>^<>vv^v<^v^^^v^^v><^^v>^^>^>v^^v<<>v<v^>v><>^>>^^^<>vvvv^^v^<^v^>>>v>^^^^>><^^>><><^>v<^>vv>^vv^>^^^vv>vvvvv<^<>^>^>vv^<>^<><>^>><^>^^vv>^<>^<^<^>><^<>>^^v^^>v^<^^^vv<<^<<^^>>>>>>>>v^><^^vv^<<<^^<^>><^>^vv>>^>^<<^^>^^v^>>v>v^>^>v>>^><^<>>>v>v><<<>^v>><<^^v<^<>v^v^v>^^v<<>><^vv>>>v^^>^v>v<^^^>>>^<^<^<^v>vv<^^<>>^vvv^^^<>v<>><<^^^^v<^vv^><^<<^<<^v^^<<^^>>>^>>v^^^v>^^^^><^>>>vv^^v<>>^v^<>>^>><^<><^<^>v>v^^><^>v<<>^<>v>>>^^vvvv^v>^<<>^v>^v^v<vv +v^>>>^^<<^<^<v>v>^<<<<><>v^^^>^>v>vv^^v<^>^<^^^<>v^>vvv^<^^^vv<>^<^>^^v>^^>v>v^vv^<^^><>v>>^^v^^>>v>v><^v><^>><<><>^vv<>v>vv><>>><v><>v^v<^^<<<>v><^><>^v>><>><^>v>^>^<<>^vv^vvv^>^<<<<><^>v<><<<^^<^^<>v>><><<^>vvv^>^>^<>^^^<^>^v><vv<<>>vv^>v>vv><<^v^>^<>v>>^vvv>^v^v^v^<<>>^^^^^<><>^><>v><^^v<^^v>v>>>^<<^^>>>v^<>v^>v^<<^>v^<^<^>v^^^v^v<^v>>^^v>^v^>>^v^v<^^><^v>^>^^v<>^^^>^>v>^><^v>>>v^><^<<<^v<^^<^>>>v><>v^v^v><>>>^>vv<<<^>>>>>^v>vvv<>>vv><^v^<^^^^^>v^^<^<>^>vvvv^^>>^^v>vv^v<^vvv><<<^<<^v><>><>^^<<><^>v^v>>v><>^<^^v>^>^>v<>v<>><^>^^>^><><^^^vv<^^^<>><><<><^vv^>^>^^>>vv^><>vv>v>v>v>v>>>^^vv^><^^^vv^^vv<>^>v>v<>vv<^>^vvvv^<<<>v^^v><^<^>><>>^^<vv^<^v>v>^v<^<^>vv^>^<^^^^><<v^vv^<<>v>><^>v<<^^v^^>^<^>v +^v>v<^^<>v<><<<^><>>^^vv^>v>^<>^^^^<<>^v>^<^<<<^>v<>>^>><^<>^v>vv>^^^<>v><^^^v>v^^>v>^^>^>>v^v>v^^^v>^>^^<^v<^<<^>vv>vv>v>vv^><<<>v>^>vv<^>>v^<><^>^v^v<<^^>v>^v^^><^<><^<<>>v^>^^^>^<<^<<<><<>vvv^v<^vvv^>^<>^<<>vv<>><>v<^>vv>>v^>vv<>v^^>vvv>>>^>><^^v^^>^>><>>^v>><><^>^>^v>^<^<>>vv<>v<><>>>^v^<<<<^>v<^v^v^<^>^v^vvv^vvv^>>v^v^v^^>><<>><>v><>>^v^<^<v<<^<v><><<>v>v>v<^^<>>vv<^^>vv^v>>>v>v>^vv>>vvv^<>v<>v^><>>vvv><v><^><^^v<>^<<^>>>>^<^^^<<^v^>v>><<<>^vv>>vv>>^<^>^^^<<^>^>>>><>^>>^<>^>v>>^>^v><>v^v^v^><^^v><<><>^<^vv><^<<^<^>v>vv<>^>^^^^vv^v^<^<^v^>v><<<<^^^vvv<<^^<<^>v><>v^<^>>>^v^>v<>>^v><^^>^^>>v<^vv^<^<^^v^<^>^>v>v^<>><<<><^<^<^^>><>>v<><^v^^<<v>><>>vv><<^v<^v<^v<>^<^>v^v<>^<^>< +><<<>^<^v>^^^v^vv^v>^>><>v<^<<^v<>^vv<>v>><<>>>v^>v^^<><>^>v<>v^>vv>>>^<><^<>v^>><>v>v>vv>^^>v<^^>v<<^<>>>>^^^^>>vv>^>v^>>>>v^v^><^vv<^^^v<<<<<>>v>^v><v^vv<<<^>^^v^^>^^^^>vv><<^<^^^<^<>><^>v^>v^v<^<>v><^^<^^>>^^v^><<^^v^^<>^>>>>>vv^<<^vvv<<^^^v>>><>>v^^>>v>>vv><<>>v>^><^>v><^>^^^^>vv>^<^^<>>v^v<<^^v>^^^<>vvv<<>^<^v<<<^>v><<<^>>>v>^v^v<<<>>><^>vvv^v^>^>^^^>>^^^<>>><v>^^v<^^>v><<>><^^^><v^<^>^>^<>><<<>>>v<<><>^v^vv^^^^^v>><>^<^^v>^><<>>vv^^>><<><>v<<^^>>^<>^^><>^<^<>vv^vv>^^^^<<><>v^v<>>vvv>^>^>><>>^v^^v>^>v^vv^^vv^>^>>>^>vvv^>v^^>^v<>><<^^<>vv>^><>^v^>^><<><>^^>>^^<<^^^v>v^>>>^^v<<<^<><<>v<^>v>^<>v>^<<>>>vv<<<>><>>v>^>>>v^<<^>v>vvv^v>vv<<^><>^<<>^^>v>v^v^v><^>><>^vv><^vv<> +>>vvv<<<>>>>^^^v>v>^^<>>>^^vvv>^<<<<>>^^<>^>><<>^^<^>v<<>v<>v<>^<><^vv^<>^<>^v>v>><<<<>^v^><^>v>v^>^>v>^<<^<>^^><<><>v^>^<<>>>v^>v><<>v^vv>vv^><<^>^v^>vv^v<>^^>vv><><^vvv^<>v<^v<>^<^<>v^vv>vv>>>vv<^>^v<^<^<>><<>v<>^>^^^>^>><><^^vvvv>>vv^<>v>>>>^<<><<><>^vv^^>^^>>><^v^><<>^^v>^>^<<><<>>>>>vv<^>^^<^^vv<^^v>>^^v>v<^<<<<<>^><^vv^>><<^>vvv>^v^^<^v<><><>>>v^<^vv>vv<>>vv>^<<^^vv^><^^vvvv>v<>v^<^v<^^><>>^vv<<>>><<^<<>v^^<>vvvv^^<>>^v<>><<^v^>>^^^v^^<^v^>^><>v<^^v>^<vvv^v>^^^<<>v^^v<><>^^vv>v>v^^v^^>>v^<>^<<<vv>^v><^v>><^>^v<^<>^v<^v<^v^>v>v^>^<<>>v^<>><^vvv>>v^<^><^><<>^^<>vv^>^^v<>v^v<^<><^v<>^^>>^<>vvv<^>^v<^>v>^>v>><<<>>v>^>^^^>>^v^v<<>^v>v>v><<<<^>^v><<>>>^>>v>>^^><^<<^>^^<^>>^^>vv^v>v^<^><<>^v^>v<^>^<><^v<^^>^^>^>^>>v^v>^><^>^vv^><<^>v^v>^^^^>>vv>v<^v^><^<<^v<<^v>><<<^<^<^><^v>><^>vv^>>v<^vvv>^><>>>>^<^<>^<^^v>>>^<vv^v<>v<><^<^>>><><<^<<>>^<^<<>v>vv^><^^<^v<<>^^^<^v<<^^vvvvv<^v<^>^<^>>>><>>>^v^<>v>^^^^v^^vv><<<^<<<>v^v<<<<^^^>>><^^>>^><^v^v^vv^^v^<>v>><<>^v<^vv^<^^v>^^>^>v>^v^>v^>v^v<^^>v<<^^>^^><v^<<>><>^^v>>v<^>^^<<^^v^>>>^vv^^^^v<>>^v><>v^^>v>v><<^>^^>>v^<>>>^^^vv>^^^><^v>^v>^^v>^>>^<^<<>>v<^>>><<>^^vvvv><>vv<>v<>^><^<>^^<<<^^^v<>^^vv^v<<^^<<^v^<^<<><^^>>>vv^>^v>v^^^<^^^^>v<^v^<^>vv^>v<><<<^>>>^^<<<^v><>>^vv<<>^^>v>^^>^>>v^^^^^^<^^<<^<^<^<^vvv<>v^<<<>v^v^>><<><^>^v<^v>>^>><>v^^>^v<<>>v<<<>v^v^vv>>^vv>v<>v^<>>v<>>v>v^^^v>>>>>v^>vv^^^v^^>>^>^v<^^>v<^><>^<^vv>>^^^< +vvv^<>^v<<^^^v><^vv>vvv>>^^><>v<><^<>^^^^<^>^^^^v<^<>vv^v>v>v><><^^>>>>>^<^^^<>v^^>vv><<<>>vv^>vv<<>v>v><^v<<^>vv<>vvvv>vvv<^v<>>^<^^v^>^vv^^vv>>v<>v>^v^vv^>^v^^^<<^v^^>><>v^^v<<^>v^v<>^^>>^<>>v<<>v<<>>^v^><>v^^^^^><><<<>^^vv>v^>^v><><^v^^vvv^>>v^^v^v<^vv^^<>v>v<>>^>vv^><^<^>>vv<^vv>^v>^^v>v^<<>^^v^v<^>v<<>^^<^>><<<^^v>>>>><vv><>^>>>v><><^v^>vv^<v^>^>><^<<^>>>>v>><<<>v>v^v^>>v^v^v<<^^^<>>^>v<>>v^v<<>vv>^^vv>vvvv<<^v^vv<><^^>^v^>>^><><^>v<^vvvv>^v^>vv>^>^<><<^^>^^^>>v<<>^vv>^>>^>^v>>>v<><>>v>^><^>>>>^^^<>v^^<>vvv^><>><<<>v^<^v^^<<>>v^^^^>>v>>>v^^<><^>vvv^>>v^<<>>>>v^^vvv^<><>v<^^>^vv<<^^^^>v<<><^<<>><<>^v>v<><<>vv>^<>>v^><>>vv<^><>><^>^v^>>>^>>v>>^v>v^v>vv<^<>>>><^>>>v^v^^v^ +v^^^vv<>^<>>^<^^v^^^<^^^v>^>v^>^vv>v>^v>>><^^^><^vvv^>^><^^<^v>>><^<>v>^^<><^^>v<<^^v<>>>>^vv^<^><v^^<^<^v<<>><^>^^><>>^vv^>vv<>>v^v<>>>>v<<><^^v<>v<>v>>^vv>v^v<<>>vv<<^>^<>^^^vv^v^^v^vv<<^^^>v>>v<>^>><<vv>vv^>^>>v>v<<><^>^<<^>v>>v>^vv<<^>v>v<^^>>^v^<<>vv><><><^>^>v^^<>v>>>v<><^>>vvvv<^vv>v^^^>><<<><^vv^^^v^v<>><^>>v^v^><^<^<vvv^v<^>^>v<<<>>v<^^vv>v^v^>^v>><<^vvv<^^<>v^^^v>v>^^>^>^^^v<>^v^<^v^>^>><<>^v<>v^><>v^>vv^^<^>v^v>^vv^^><^<<<<><>^vv>>>^v^^>v<^><>^<^<<^v>v^vv><><v>><>>^^v^>^^v>>^^<^<<<>>v<<<^<><>v^vv^^<<>^<<<<^><>^>>^vv^<>v>^^>v<><<^>><>^vv>>>v^^^v^>v><>^v<<><<<><<^vv>^>v^>vv^<^><^<^<>^>>>v^>^><>^v><^vv^^^>^>^<<<^v>v^^>>>v<>^v<<^<<^>v>^><^<vv^<>><>^^><<^^>v>v>>vv<>><<><^<<><^>^v<>>^v><^<>>^<>^v^vv<^v<<^v^^v>^><<<>^v^v><<^<>v^v^vv<<>v^><>v^^v^^<>^v>vvvvv^^^<^^>>>v<>^^<^^<><<>>vv>vv>v><^vv^^<^<^<><<^v<^>>^v>vvv<^^>>v>>vv>>^<><<<>v<>^vv^>vv^>v<>>>^v>>^>^^<>v><^vv<^^v^v>>><>v>v<^v<^^<<^vvv^^<>><<><><^^<^>><>><<<<v^>>>v>>^<^vv>>><^v<>>^^v^v>^^<^<>v^>^^><^^>><^>v<<<^^vvv><^^v^<>>v<<<^v<<>>vv^><^<<>vv>>>vv><<<<>^v><^<>vv^vv<^v<^^v^^^^>v>vv^^>^v>v^vvv^<v^>>>><^v>^^v>>^><^^v<>v^v^<<<<>>>^v<>^>>^^^>v^<^>^^>>^^^^^<^<^v^>v>vv><^<^^>>v^v<<>^<<>>^^^v<^^<>v^^^>>><<^>><>^>>v<v<<^>v>v><>^^>^v^<<><>^^^^><<<>^v^v<^^><>>vv>^^>^^^v<>^^>^<^v>vv^<<<>v^<^^<><<<<^<^v><^<^v><>vv>>v>^>>^v><>><>^>v^>v>v<>^v^^v^>>>>>>^v^v>v><<^v>^<>vv^v>>^v<^^>^>v^>><<^^<>^>v><<<^v^^^^v>>>^^^v><^^v>v^<>^v>^v<<><^v<^v<>v^v><^^v>^>^v<^< +<^^vv>^^<<^<^>^v>^^<<>^<^<>>^>^<<^<^v>^>>>vv<^^<<>^><^^<>><<^^>>>v^>^<<^>>vv^><^v>^>>v<><<><<^v<>^^<<>v>^v<^^^<>^^^<^<>><<<<<>v^^<<>^^v^>vv>>v>^>^<><<>v<^v^^v<>vv>v^v>><>>>>^>v<><^>v>v>v>vv^v>v<<>>>^^<<>^v>^>^v^^<^^>>^v^<>v^^>v^><<^vvvv>>v^v^vv>^v>^vv<^>vv^v<^>>>^<>v^^><^<<^vv<^<^v<>>>^<v^^^vv>v^vv<^>>vv<<<^>v^^>^><>><^vv<^<^vv^>^vv<^^vv^<<>>vvv^v^v<^>^vv^v>vv>^^>vv^vvv^v^^>^vv<^^>v>>>>^>v><>>vv^^^<^>>v>vv^>vv<>^^^<>^^v^>>^^><>v>>>v>vvv<<>^^^^><<<^><>^v^^<<<>><<>><><>>vv<<^^v>>>^^v<^<^^^^vv><>v<^^<>^>>>>>>>>vv>^^v>>^<<^^^v>>>^v<<^<>vv^>>^>><^>^v<>vvv>>^>^v>^^v>>^^<<>vv>>^v><^<>^<>^v>^^vv<^<<>v><<>><<^><^<<^<^v<><^><vv>>^^^<>>v>v<^<<>>v^><<<<>>^v^v>^^<>>>^<>v>>v><<^>^>^<<>^>vv<^v<>>^>v^>^vv<> +<<>^<>v<^<>^>>>^<^v>><^>v<^v<<v^v><^>^^v>>v>v>v^<^v^v<<^>^vvvvv^^><>^^^v>>^<<>vv<>>>v^>^>v>vvv>><<<<^v<>><>^^^vv<^><<><<>>v^>v^<^v<^^><>v^vv>^^>>v<^>v<>>><^vv^<>>^><>^>v<>><^<>v^>^^v<<<^v<><^^v^<^^>>^>>>vv<>^<^<>>vv^^^>v>^v^<>v^<^v<><>vv^^<>^^>v<^>vv>vvvv<>v<<^<<<<>><^^<^<^<<^>>>>v^v><>^<>v<^<v^^<><^>^v^^^v<^vvvv>>vv>v<>><>v<<^<>v<>>>v>^>v<^v>>v<<>v>>^v>^^<^^><^^<<^^>vv^<^v>>^>v^vvv^<>^>vv^vvv>v<>><<<^^v<<^^v>>>^vv^v^<>>v<>^^><^>v><<^^><>>v^^v^v>>>>^^v>^^>>>^v>^vv>v<>^>v>v^v<^^^>><<<>^v>^<><><>>>v^><<^>^v^<^v^<<<<<^>v^>v>^v^>^^vv<<v<><<<^vvv<>>^>^v>><<^>^<^<^^v^<<^<^^>v^^>v^><^v^<^v^><^^<>^>>vvv>>>>vv>><><^v^<<^<^^v^>>vv><^^v>v<>v>vv^<^<<>vv^^><><>>>^<^<^v^^>v^><>^<>><^>v<<^v^^>v^>^v>><<^<^vv><<>>^ +^<^>>><><>vv>>v>v<>>^<^<><>v>v>>vv^^^vv^<^v<<>>^>^^v^vv>vv>><vvv<v^^>^v>>^v>^><<<<^^>^v>v^><^vv^<>><^v<^v>^>>>><<<^^<^vvv>v>^^>v>^>>><><>>vv<<><><><>vv>^vv>>vv^>v<^v>>^^v^<<^v^^v^<><>><>^>^^>^v^>>>>><<>^>^v<^<>>^^<>>^^>^v^>v^v><>^^v<^^^^vv^^<^<^<^^^^<>v^v^^><>>>^<>^^v<>^>><<^^<<<<><^>vvv<<<>v>>vv><><>>v>vv><>^v<<>>v>vvv<<^v^vv><>v^>v>^v<^vv><<^<><^^>^>^v<^<>^^<^>v>v<^v<>><>>^v><<>vv<>v>v^<>v^^v<^>^>^>>v^^^>>^>><^vv>><^^>>>>><<>^^v<<>^^v^>^>^v>>^^>^>^>>>v><^<><^>^<<>^vvv^vvv^><^<><>v<>>^<<^>>^v>>^^^>^^<^^><>^^^v^vvvv^^^v<<^>^v^^^v<^>^><>^>><>^v>vv^^>>vv<<<>><>^>vvvv>v^v^v^>v>v<<<>v<<<<>v^^^>v>v<><^<^v>^vvv><<<>^<><^^^^^vv^^^<^<^<^>^vvvv<^<<<^<^<^<>>v +<^<^>v^>v^>^v<><><<^>v<>v>>^^^^v<>^^<<^<>>vvvvv>vv>v^>^<>v^v>^^>v^vv^>vv^<>^>>^^^^vv<<<^<<^>^>^v><<>><>v<v<<^v^><>^>^>>^^v>^^>^<<<^>^^vv<<>v<v^><<^v^vv<v^><>>>>>^<>><><^>v<^^^>^<^>vv<^<v^>vv^^>>^^>^>^><<^vv^^>v>v<<>^^^<<^^>v><<^><>^<^>v<<^v<>v^>^vv^^<^^<>^<>>^vv>>>>>v>vv>>>^<<<<<^>>vv>>v<<>^<^<<^v^>>^^v<^>v>v<>><>^v^v<>^v<><^v<^^v^<>^v>>>vv^^>^>vv^v<^v^>^vv>>^<<>v^v>vv^>>v>^vvv^<^<<v><<^>^v^v^<<>^v^^>v>^<<>^<<^>^>v<<^^^>v>^^v^>^><<>^^v>vv<>vv^vv<>>^^^<^vv^^>><>^vv><>>>^>^^v^><>v^v^<^<^<><^^v><^^^><v<>v^>^><><^<<^v^v<>>^^<<><>vv^>^^^<<>^<^vvv>vvv^v>>^^<v^^>^>v<^^v<<>v><>^<>v^^^^^v><v^<^v^^^<^><^v<>>>^v^^<<>><><>v>^<>>v>><>^vv>^<^<^>>^v^>^v>v<>v<><>>v^>v<^>>v<v><^>^>v<>>v<^<>vvv^v<^v^^^v>^>^<<^<<>v^v>^^> +>>v>>^>v^<>^^vv><>><^v<<<>^>><^<>>^^<^><<<<>>^^>v^v>vv>v>^vv>><^^>v>><<^><><>^v^^vv<>>>><^<^><>v<^^><<<<>>v^<<><^^vv^^v^^<^><vvv<^<^vv^v>>v>>^>>vv>v^^<>vvvv<^^><^<><^>^^>>>>^>>>^v><<^v^^><><><^>>><>v>v>^>v<<<>v<>v>^v<>^<<<^v>>v>v><<>^>^<>v<^^>^^v^<>^<>v^>^>><^v^vv>^^^^^vv>>>^^>><>v<>v<^>^v><>vv<<^v<>vv^v^>vv^><^vvvvvv^vv<>^>vv>v>><>^v^v>v<^<^^^<>^^v^^<<>vv^^>^<>>>>^<>^^>^v<<<>>v>^<^>vv>v^>>v>^^v>^^vv^>v><>v<^><<><<<<^<>^<>vv>^^>>v<^vv><^<^<>v^v<><>^^>>>v^>>>>v>>^<^<^vv>v^vv>v^<^<><^>>v>^<<><^vv<^>^<>^>>v<^v><<^<<^<<<^>^<<^^<>vvvv^<^v^<<<>><^v^^^<<<><<>>vv^^v^^<<>><^v<<<<<>v>^><^>>v^^>^^<<^<^^^>^>^>^>v^^<><^<<<>^<^>^<<<>>v^vv<<^v<^>>vv<^v><>^>vv<^v>vv<><<>v^^>^v<^<^>^^v^>v><^<^>>>><^^<>^^<<^vv^^v<^>v^v>>vvv +<<^><<><^vv><<v<^vv>^v>^>vv<^vv^^v>^v>^>>^^<^^v^<^vv<>v^<<^^<vv^><<^^vv^v^<<<^^>>>^^>^vv>^^vvv<^<^>^^^<<><><^v<^^>v^v<^>^>v^<>^<>^><>v><^><^^>><><<>^^v>>>>v>vvv<>>^^^^<>^>^v^v^^^><^^^v><>v^<^^^^<>v>v<^>>^<<<^<<^>>>><^vvvvv>>>^<^v>>vv^>v^vvv>><^^<<^<<>^>^^>^<^^v>v>^vv><>vv^<><<^v>^^vvvv<<^^v>v<^^v>>v<^^v^v^v<^v^>^>vvvv^v^vv><>v^v^^<<>^>>>v<><<><^<^^^><^<<>^^v>>>>^v^<^>^^>><^>>^v<^v><>>v>><^^>>><<<<^^<vvv^^v>^>>^><<<^<^>v^>v^^><<^>^^^v<<^v^>^vv^^vv^<^>>v>^<^v<<>^^>v^><>^<<^>^v^vvv^^^^^v^v<^v>^>vv<^>^>^>v^^<^^^>^><^><<>v^<>^^v>>vv<<<>><>v>^<^^>v>vv^vv<<^v<>^^^>><<><<^^>v<^^><><><<^>^^v>^v<<>>v^^>>><>>v^v<>v<>><><<^^^v^<<^>v<>^><^^^v^<^<<<^v<^vvvv>v>>>^vvv +v>^<^>^>^<<>^^>^^v^vv>>>vvv<^^<^v><>>^^v>vv<^v>>v><>vvv>v>>>vvv^vv>v<^>vvv^><^<<^v<^^>>>>v>vv<^<<<^>>>v^vv><^^v<<><<<^^<<>^v^v<<^>v<^v><^>^>><<>^^>^>^v<<^^>^^>>v>v>v<^^v>^>v>^vvv><<^vv<^^v^v<>vv<>vv^v>^v^>^<^<<^^^vv^>>^><><<^vvvv<><<>^^><<<^>vv<^v>v>><<>vv^^<^v<<>v^<<>^<<^v^>>><>v^>^^>>vvv>v>><>v<^>vv<<>^^v<>>><^^<>vv^>v^vv<>^>v<^v<<>v>vvv>v>^>^<<^v>v^^<^>^>^>>>>>v<<>^<>v^^<<><>^^v^^^^<^v><^<<^<>^^^<^>^>v^^v^^<>^vv>><><>^^<<>vvv^>^vvv>v>^vv>v<>vv<<<><^>>vvvv<^^<^v^<<^<><>v^^v<^>^v<^<><^><<<<>v<^v>v><>v<<^<^>^v<>v^>>vv>^v><^<>>><^v^<^^<>v^v^<<<^v<><>v^vv^vv>v^>>v<>>><>^><<>v>v><<>^^v<^v^vv>^vv^>v^^^^^^v>>^v<<<vvv<^vv^v^>^>>v>>><>vv>>v^<^^<<vv>v^<><^>><<<>><>^>v<^<>v^^>>>v<<^^v^<^^<>><^>^>^^>>><>^^>^><^<^>v><<>^>^<^^v<>^>v<>v<><^v>v<>v^^vv>>vv<^^v>vvv>v^^v>^vv<>^<<<<^>v<^>>><^v>v>>>v>>v>v>^<>^<^^v>^>>v^v>vv^><^>vvv>^>>v^v^<<<>^^v^^<^<<<>vv>vv^^<^<>vv^>v<^^^v<<^<^<><>^vv^vv^>vvvvv^<^^^v^^<<^^<>^^<<<>^v^>v><>>>vv><^^>>vv>>^<^^<^v>^>^<><^v^^<^vv>v<v^<^<^vv<>v<<>>^v<<^>>vv^^<<v>^<><<>vv><^^v^v<^^^^^><^>vv>^^^^vv>^<<^<^>^v>^^^v>>vv^v<><>^<^><>><><^>^^><<>>vv^>>><^v<<^^>^^><>v<<^>>v<<^vv^>>><<>vv<>^^^^^<^v>v^^vv>^^^<^^^vv>^^v>vv>^v^>><^>>v^^v>><>>^v>v>^<>vvv^^v<^>><>v><>>v^<^<<>^^<<^^>vv^^<>^>^<<>^vv>><<>^v><<<><^^^v^^><>^>>>>v^><<><<^v<^v<>v>><^>>>^^v^^^>^<>^^^^>>v<<<^^^vv<^<<^^v^^<^v^<^v<><>>>^<^^v<<v>v^>>>v>^<>^>^<^>>v^v^^^>><>><><><^^<<>>>>>vv>>^<><^<><><<<>^>vv<^v<^^<^v^>vvv^>v^>>><<^^^>><^><^<><<^<vv<^v>><<^<>^^<>vv>v<>^>>vvvv^>^v>v><>^v +><^<^v^^<>vv>>v<^v>v^v>v>v^^>v^v<>^><^>>^>>^v<>v^^v>^vvvv<v^>v^<>>^^vv<<>v^v^<>v><>>>>>^^>>^v^>^<>>v>>^^^v^<^^^^v>vv^<^>^v>><^<<>v>v^>^>^v>^><>vvv^v>>^vv^>^vv^^^^v>vv<><>>>^<^^>>^><<<><>^><>^^v<>v^><^>v>>>^>v^vvv^^<>v^^^>^^^^>>>>>v^>vv>^<^>^v><^^><^v>v>^<>^^>v<^v>vvvv<>^v<>^<^<^v>^>v>^^>^vv>^^<>>v>^<^<<^>v><>>>^vv<<^><>>v^>^<>^v>>>^<vv>>^^v<^><^vv>^<>v>^<>^<^>>>>>><<>>v>>v<<^>^<>>^<^><^>^<^^^<>>v<>^^><^>>vv>>>><^<><<<^^><^^vv>^v^>^<^>>^>><<^>v<^^>vv^>^>v>^v^vv^>v>^^>>v<>^>>v>>v<>>^^<^v<<>>><>>vv<^>^^vvv<>^v>v^v><>v<^v^v>v<>>^v>^^^^vvv<<^v>><^^>v^^^v<>><^>^v^vvv<>v>^>>>v<<>v>^<><>>^>vv>v>^^v>^^<^^^v<<^<^vv>v^><>>^v>v^<^^^vvv>v>vv>v^>>^v^<>v<>><<<>>^v^^^<>><>>v<>v<<<^>v^>v<^<<<><^<<>^^^v><<>><<^<><^><>>^>^^>vv<><^v^v>^><^>^<<>>>^v^^v>^v<^<>^<>^>^vv>>^<^^vv^^^^>^<^<>>^>vvv<<^v^><^v<>vv>^>v>^>vvvv^><><^>^v^<>><^^^><<>v<<^^^<^<><^v>^<<^^v^<><>vv^v^^vvv^^^><<^^<>>^<^v^vvv<^vvv^v^^>^v^^<^v>^vvvv>^>v<<>>>v>^v<><^^^^^<^^<^v^<>><<<>>^>^^v^^><<<^^vv^<^<^<^^<>vvv>v^^v><>v>>v^><>>>><>vvv^<<^<>>>>^>v<<^^^v^^^>^<<<^vv<^>>><^<^v^<^v^>>v<^^>^^v^^^^^>^>v^v^vv^^>v^v>>^vvvv>^<<<<>v<>v<>v^>>>>v<^vv>v^>><<>vv^^v^v>v>v<>v<>^>>vv^<>v><^>>vvvvvvvvvv^^v<<^>^>>>>^>><^v>><<^v^^<^vvv^^vv^>>vv>^>v^vv>v<<<>vv^v>^>v^^v^v>>^vv<>v^v>>^<>^^>>>>vvvv^v>v^>><<>>^<<<>v>^v^><><^>^^^<>v^^^>^><^v>^^v^<>>>><<^>v>v><^v<<^>v<<<>^>^^^<>>v><<^<^>><^v^v^<<>>>v^><^v><>v^v^><>>v<>v>^v><<<>^><^v<^^<^<^>vv^><^v<^>vv>>v><<^>vv>^<^>^vvv^vv<<<><<>vv^v^^vv^vv<^><<>v^v<><>v>^><<><>^>>^v^v \ No newline at end of file diff --git a/aoc2024/test/day15/python/test_solution.py b/aoc2024/test/day15/python/test_solution.py new file mode 100644 index 0000000..96d0550 --- /dev/null +++ b/aoc2024/test/day15/python/test_solution.py @@ -0,0 +1,36 @@ +# Copyright 2024 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +import unittest + +from common.python3.AdventOfCodeTestCase import AdventOfCodeTestCase +from aoc2024.src.day15.python.solution import sum_all_boxes_gps_coordinates + + +class TestSolution(AdventOfCodeTestCase): + def __init__(self, *args, **kwargs): + (super(TestSolution, self).__init__(__file__, *args, + **kwargs)) + + def test_part1_withExample_correct(self): + self.assertEqual(2028, sum_all_boxes_gps_coordinates(self.examples[0])) + + def test_part1_withLargerExample_correct(self): + self.assertEqual(10092, sum_all_boxes_gps_coordinates(self.examples[1])) + + def test_part1_withPuzzleInput_correct(self): + self.assertEqual(1383666, sum_all_boxes_gps_coordinates(self.input)) + + +if __name__ == '__main__': + unittest.main()