Skip to content

Commit

Permalink
docs: day24
Browse files Browse the repository at this point in the history
  • Loading branch information
alex-ong committed Dec 30, 2023
1 parent 618f3a8 commit d122475
Show file tree
Hide file tree
Showing 8 changed files with 43 additions and 1 deletion.
1 change: 1 addition & 0 deletions day24/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
"""Day 24 solution."""
10 changes: 9 additions & 1 deletion day24/day24.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
"""day24 solution"""
"""day24 solution."""
from typing import Optional

import z3
Expand All @@ -11,6 +11,7 @@


def get_intersection_2d(left: Hailstone, right: Hailstone) -> Optional[Vector2]:
"""Returns intersection of two hailstones."""
pos1 = left.position.xy
dir1 = left.velocity.xy
pos2 = right.position.xy
Expand All @@ -33,10 +34,15 @@ def get_intersection_2d(left: Hailstone, right: Hailstone) -> Optional[Vector2]:


def within_2d(point: Vector2, min_max: Vector2) -> bool:
"""Returns whether a point is inside a given rectangle.
x and y are both symmetric and defined by min_max.
"""
return min_max.x <= point.x <= min_max.y and min_max.x <= point.y <= min_max.y


def part1(hailstones: list[Hailstone], valid_range: Vector2) -> int:
"""Solve part1: list of hailstones that are within a given rectangle."""
result = 0
print(len(hailstones))
left: Hailstone
Expand All @@ -55,6 +61,7 @@ def part1(hailstones: list[Hailstone], valid_range: Vector2) -> int:


def part2(hailstones: list[Hailstone]) -> int:
"""Solve part2: a magic hailstone that passes through all other hailstones."""
x, y, z = z3.Reals("x y z")
vx, vy, vz = z3.Reals("vx vy vz")

Expand Down Expand Up @@ -90,6 +97,7 @@ def part2(hailstones: list[Hailstone]) -> int:


def main() -> None:
"""Loads input then solves."""
input_data, valid_range = INPUT

hailstones: list[Hailstone] = parse_input(input_data)
Expand Down
1 change: 1 addition & 0 deletions day24/lib/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
"""Day24 library modules."""
8 changes: 8 additions & 0 deletions day24/lib/classes.py
Original file line number Diff line number Diff line change
@@ -1,24 +1,32 @@
"""Day24 classes."""
from dataclasses import dataclass


@dataclass(frozen=True, slots=True)
class Vector3:
"""Simple 3d vector."""

x: float
y: float
z: float

@property
def xy(self) -> "Vector2":
"""Convert to vector2."""
return Vector2(self.x, self.y)


@dataclass(frozen=True, slots=True)
class Vector2:
"""Simple vector2."""

x: float
y: float


@dataclass(frozen=True)
class Hailstone:
"""Hailstone has a 3d vector for pos/velocity."""

position: Vector3
velocity: Vector3
15 changes: 15 additions & 0 deletions day24/lib/parsers.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,28 @@
"""Day23 parsers."""
from day24.lib.classes import Hailstone, Vector3


def parse_vector3(line: str) -> Vector3:
"""Parse a vector3.
E.g. 1,2,3
"""
line = line.strip()
x, y, z = line.split(",")
return Vector3(int(x), int(y), int(z))


def parse_input(filename: str) -> list[Hailstone]:
r"""Parse input lines.
Lines in the format ``1,2,3@4,5,6\n``.
Args:
filename (str): file to open
Returns:
list[Hailstone]: list of Hailstones
"""
result: list[Hailstone] = []
with open(filename, "r", encoding="utf8") as file:
for line in file:
Expand Down
1 change: 1 addition & 0 deletions day24/tests/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
"""day24 tests."""
5 changes: 5 additions & 0 deletions day24/tests/test_day24.py
Original file line number Diff line number Diff line change
@@ -1,28 +1,33 @@
"""Test main functions in day24."""
from day24.day24 import INPUT_SMALL, get_intersection_2d, part1, part2, within_2d
from day24.lib.classes import Hailstone, Vector2, Vector3
from day24.lib.parsers import parse_input


def test_part1() -> None:
"""Test ``part1()``."""
file_path, valid_range = INPUT_SMALL
hailstones: list[Hailstone] = parse_input(file_path)
assert part1(hailstones, valid_range) == 2


def test_part2() -> None:
"""Test ``part2()``."""
file_path, valid_range = INPUT_SMALL
hailstones: list[Hailstone] = parse_input(file_path)
assert part2(hailstones) == 47


def test_get_intersection_2d() -> None:
"""Test ``get_intersection_2d()``."""
hailstone_a = Hailstone(Vector3(20, 25, 34), Vector3(-2, -2, -4))
hailstone_b = Hailstone(Vector3(12, 31, 28), Vector3(-1, -2, -1))

assert get_intersection_2d(hailstone_a, hailstone_b) == Vector2(-2, 3)


def test_within_2d() -> None:
"""Test ``within_2d()``."""
valid_range = Vector2(7, 27)
v1 = Vector2(14 + 1 / 3, 15 + 1 / 3)
v2 = Vector2(11 + 6 / 9, 16 + 6 / 9)
Expand Down
3 changes: 3 additions & 0 deletions day24/tests/test_parsers.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
"""Test parsing functions."""
from day24.day24 import INPUT_SMALL
from day24.lib.classes import Hailstone, Vector3
from day24.lib.parsers import parse_input, parse_vector3


def test_vector3() -> None:
"""Test ``parse_vector3()``."""
v1: Vector3 = parse_vector3(" 2, 4, 8")
assert v1.x == 2
assert v1.y == 4
Expand All @@ -16,6 +18,7 @@ def test_vector3() -> None:


def test_parser() -> None:
"""Test ``parse_input()``."""
file_path, _ = INPUT_SMALL
hailstones: list[Hailstone] = parse_input(file_path)

Expand Down

0 comments on commit d122475

Please sign in to comment.