Skip to content

Commit

Permalink
AoC 2024 day 14 part 1
Browse files Browse the repository at this point in the history
  • Loading branch information
loociano committed Dec 14, 2024
1 parent 0286577 commit fbd7d6f
Show file tree
Hide file tree
Showing 8 changed files with 629 additions and 0 deletions.
Empty file added aoc2024/src/day14/__init__.py
Empty file.
Empty file.
83 changes: 83 additions & 0 deletions aoc2024/src/day14/python/solution.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
# 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 re
import math
from typing import Sequence
from collections import Counter

type Position = tuple[int, int] # (x,y)
type Velocity = tuple[int, int] # (dx,dy)
type WorldSize = tuple[int, int] # (width, height)

_DEFAULT_SIZE: WorldSize = (101, 103)


class Robot:
def __init__(self, position: Position, velocity: Velocity, world_size: WorldSize) -> None:
self._x = position[0]
self._y = position[1]
self._dx = velocity[0]
self._dy = velocity[1]
self._width = world_size[0]
self._height = world_size[1]

def move(self) -> None:
self._x += self._dx
if self._x > self._width - 1:
self._x -= self._width # Wrap around right edge.
if self._x < 0:
self._x = self._width + self._x # Wrap around left edge.
self._y += self._dy
if self._y > self._height - 1:
self._y -= self._height # Wrap around bottom edge.
if self._y < 0:
self._y = self._height + self._y

def get_quadrant(self) -> int:
"""Returns the quadrant where the robot is located.
Quadrant can be 1, 2, 3, 4 or 0 if located between quadrants."""
mid_x = self._width // 2
mid_y = self._height // 2
if 0 <= self._x < mid_x and 0 <= self._y < mid_y:
return 1
if mid_x < self._x < self._width and 0 <= self._y < mid_y:
return 2
if 0 <= self._x < mid_x and mid_y < self._y < self._height:
return 3
if mid_x < self._x < self._width and mid_y < self._y < self._height:
return 4
return 0 # At quadrant division.


def _parse(input: Sequence[str], world_size: WorldSize) -> tuple[Robot, ...]:
robots = []
for line in input:
matches = re.match(r'p=(-?\d+),(-?\d+) v=(-?\d+),(-?\d+)', line)
if matches is None:
raise ValueError(f'Cannot parse input line: {line}')
position = int(matches[1]), int(matches[2])
velocity = int(matches[3]), int(matches[4])
robots.append(Robot(position, velocity, world_size))
return tuple(robots)


def get_safety_factor(input: Sequence[str], world_size: WorldSize = _DEFAULT_SIZE,
elapsed_seconds: int = 0) -> int:
robots = _parse(input, world_size)
for _ in range(elapsed_seconds):
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))
Empty file added aoc2024/test/day14/__init__.py
Empty file.
Empty file.
12 changes: 12 additions & 0 deletions aoc2024/test/day14/python/example1.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
p=0,4 v=3,-3
p=6,3 v=-1,-3
p=10,3 v=-1,2
p=2,0 v=2,-1
p=0,0 v=1,3
p=3,0 v=-2,-2
p=7,6 v=-1,-3
p=3,0 v=-1,-2
p=9,3 v=2,3
p=7,3 v=-1,2
p=2,4 v=2,-3
p=9,5 v=-3,-3
Loading

0 comments on commit fbd7d6f

Please sign in to comment.