From 815068e02a805e21f57ffa0a6470a55935c116fe Mon Sep 17 00:00:00 2001 From: Luc Rubio Date: Sun, 15 Dec 2024 00:06:28 +0100 Subject: [PATCH] AoC 2024 day 14 part 2 --- aoc2024/src/day14/python/solution.py | 52 +++++++++- aoc2024/test/day14/python/test_solution.py | 111 ++++++++++++++++++++- 2 files changed, 158 insertions(+), 5 deletions(-) diff --git a/aoc2024/src/day14/python/solution.py b/aoc2024/src/day14/python/solution.py index 827ae4c..499daea 100644 --- a/aoc2024/src/day14/python/solution.py +++ b/aoc2024/src/day14/python/solution.py @@ -32,6 +32,9 @@ def __init__(self, position: Position, velocity: Velocity, world_size: WorldSize self._width = world_size[0] self._height = world_size[1] + def position(self) -> Position: + return self._x, self._y + def move(self) -> None: """Moves robot from its position according to its constant velocity.""" self._x += self._dx @@ -74,14 +77,55 @@ def _parse(input: Sequence[str], world_size: WorldSize) -> tuple[Robot, ...]: return tuple(robots) +def _simulate(robots: tuple[Robot, ...], elapsed_seconds): + for _ in range(elapsed_seconds): + for robot in robots: + robot.move() + + +def _calc_safety_factor(robots: tuple[Robot, ...]) -> int: + quadrant_counts = Counter(map(lambda r: r.get_quadrant(), robots)) + # Assumes there will be at least one robot per quadrant. + return math.prod(quadrant_counts.get(quadrant_num) for quadrant_num in range(1, 5)) + + def get_safety_factor(input: Sequence[str], world_size: WorldSize = _DEFAULT_SIZE, elapsed_seconds: int = 0) -> int: """Returns safety factor as the multiplication of robots per quadrant after a number of seconds. Robots that end up between quadrants do not count towards safety factor.""" robots = _parse(input, world_size) - for _ in range(elapsed_seconds): + _simulate(robots, elapsed_seconds) + return _calc_safety_factor(robots) + + +def _print_world(robots: tuple[Robot, ...], world_size: WorldSize) -> None: + counter = Counter(map(lambda r: r.position(), robots)) + for y in range(world_size[1]): + line = [] + for x in range(world_size[0]): + line.append('X' if counter.get((x, y)) is not None else '.') + print(''.join(line)) + + +def get_seconds_to_easter_egg(input: Sequence[str], world_size: WorldSize = _DEFAULT_SIZE, + elapsed_seconds: int = 0) -> int: + """Returns number of seconds that must elapse to display an Easter egg. + The Easter egg is a picture of a Christmas tree. + """ + robots = _parse(input, world_size) + min_safety_factor = math.inf + result = 0 + for t in range(1, elapsed_seconds + 1): for robot in robots: robot.move() - quadrant_counts = Counter(map(lambda r: r.get_quadrant(), robots)) - # Assumes there will be at least one robot per quadrant. - return math.prod(quadrant_counts.get(quadrant_num) for quadrant_num in range(1, 5)) + safety_factor = _calc_safety_factor(robots) + # Thanks to reddit.com/r/adventofcode we know that the picture is small and + # fits in one quadrant. In other words, it's when the safest factor is the + # lowest. + if safety_factor < min_safety_factor: + min_safety_factor = safety_factor + result = t + # Only print state when finding a lower safety factor. + print(f't={t}') + _print_world(robots, world_size) + return result diff --git a/aoc2024/test/day14/python/test_solution.py b/aoc2024/test/day14/python/test_solution.py index b8d61d4..3e0e365 100644 --- a/aoc2024/test/day14/python/test_solution.py +++ b/aoc2024/test/day14/python/test_solution.py @@ -14,7 +14,7 @@ import unittest from common.python3.AdventOfCodeTestCase import AdventOfCodeTestCase -from aoc2024.src.day14.python.solution import get_safety_factor +from aoc2024.src.day14.python.solution import get_safety_factor, get_seconds_to_easter_egg class TestSolution(AdventOfCodeTestCase): @@ -29,6 +29,115 @@ def test_part1_withExample_correct(self): def test_part1_withPuzzleInput_correct(self): self.assertEqual(215987200, get_safety_factor(self.input, elapsed_seconds=100)) + def test_part2_withPuzzleInput_correct(self): + self.assertEqual(8050, get_seconds_to_easter_egg(self.input, elapsed_seconds=10000)) + """ + t=8050 + ..................................................................................................... + ............X........................................................................................ + ............................................................................................X........ + ......X.........................................................X.................................... + ................X.................................................................................... + .........................X........................................................X.................. + .............................X....................................................................... + ...........................................................X......................................... + X.................................................................................................... + ...................................X.........................................................X....... + ...................................................X................................................. + .............................................................................................X....... + ......................X.................................X............................................ + ..X......................................................................................X........... + ..................................................................................................... + .......X.........................X................................................................... + ..................................................................................................... + ......................................XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX................................ + ...........X..........................X.............................X................................ + ......................................X.............................X................................ + ......................................X.............................X..X....X........................ + ........X.............................X.............................X...........................X.... + ......................................X..............X..............X....................X........... + .......................X..............X.............XXX.............X................................ + ......................................X............XXXXX............X........X....................... + ......................................X...........XXXXXXX...........X................................ + .....X................................X..........XXXXXXXXX..........X................................ + ......................................X............XXXXX............X......X......................... + ......................................X...........XXXXXXX...........X................................ + X.....................................X..........XXXXXXXXX..........X................................ + ......................................X.........XXXXXXXXXXX.........X....X........................... + ......X...........X...................X........XXXXXXXXXXXXX........X...................X..X......... + ......................................X..........XXXXXXXXX..........X................................ + .X....................................X.........XXXXXXXXXXX.........X.....X.X...................X.... + ......................................X........XXXXXXXXXXXXX........X................................ + ........X...........X.................X.......XXXXXXXXXXXXXXX.......X...............X................ + .......X.......X......................X......XXXXXXXXXXXXXXXXX......X................................ + ............................X.........X........XXXXXXXXXXXXX........X......................X....X.... + ..............X.......................X.......XXXXXXXXXXXXXXX.......X................................ + ........................X.............X......XXXXXXXXXXXXXXXXX......X....................X........... + X.X...................................X.....XXXXXXXXXXXXXXXXXXX.....X...X............................ + ......................................X....XXXXXXXXXXXXXXXXXXXXX....X...........X.................... + ..............................X.......X.............XXX.............X.X.............................. + ......................................X.............XXX.............X................................ + ......................................X.............XXX.............X.................X.............. + ..................X.......X....X......X.............................X................................ + ......................................X.............................X................................ + ......................................X.............................X.........X.....X................ + ......................................X.............................X................................ + ......................................XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX................................ + .......X...................................................................................X......... + ...........................................................X......................................... + ...X................................................................X................................ + ................................................................................X.................... + ..................................................................................................... + ...X................................................................................................. + ...........................X......................................................................... + .......................................................................X............................. + ..............X.........X......................................X..................X.................. + .....................................................................................X..X.......X.... + ....................X................................................................................ + ..................................................................................................... + ................................................................................................X.... + ...........X......................................................................................... + .......................X............................X.X.............................................. + ..................................................................................................... + ..................................................X.X..........................X..................... + ...............X......................................................X.............................. + X...................................................................................X................ + ...................................................X......................................X.......... + ...............................................X..................................................... + .................................................................X................................... + .........X......................X.X...............X.................................X................ + ..................................................................................................... + .X................................................................................................... + ...........................................X.........X............................................... + ..............X...........................X........................................................X. + ..................................................................................................... + ........................................X.................X.......................................... + ..................................................................................................... + ................................................................X.................................... + ............................................X.................X.............X.....X..........X....... + .....................................................X............................................... + ..................X......................X.......X....................X.............................. + ...............................................................X..............X.........X............ + .......X....................................................................................X........ + ...............X......................................................................X.............. + .................................................................X................................... + ................................................X.................................................... + ..................................................................................................... + ......X............................................X................................................. + ...............................................................X......X.............................. + ..................................................................................................... + ..................................................................................................... + ..................................................................................................... + .............X........X.............................................................................. + ................................................................................................X.... + ..................................................................................................... + ...X...................X.......................X..............................................X...... + .......................................................................X............................. + ...........................................................X......................................... + .......X.................X.....................................................X......X.............. + .........................................................X........................................... + """ + if __name__ == '__main__': unittest.main()