Skip to content

Commit

Permalink
docs: day03
Browse files Browse the repository at this point in the history
  • Loading branch information
alex-ong committed Dec 29, 2023
1 parent d7e52fe commit 68a5a9f
Show file tree
Hide file tree
Showing 6 changed files with 34 additions and 12 deletions.
6 changes: 4 additions & 2 deletions day03/day3.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
"""Day 3 implementation
"""
"""Day 3 implementation."""


from day03.lib.classes import Gear, Matrix, PartNumber
Expand All @@ -10,15 +9,18 @@


def part1(part_numbers: list[PartNumber]) -> int:
"""Return sum of valid partnumbers."""
return sum([part_number.value for part_number in part_numbers])


def part2(part_numbers: list[PartNumber], matrix: Matrix) -> int:
"""Return sum of valid gear values."""
gears: list[Gear] = matrix.get_gears(part_numbers)
return sum(gear.gear_ratio for gear in gears)


def main() -> None:
"""Main entrypoint; grab input then run part1 and part2."""
matrix: Matrix = get_matrix(INPUT)
part_numbers: list["PartNumber"] = matrix.get_part_numbers()
part_numbers = matrix.filter_engine_parts(part_numbers)
Expand Down
2 changes: 1 addition & 1 deletion day03/lib/__init__.py
Original file line number Diff line number Diff line change
@@ -1 +1 @@
"""day03 classes."""
"""day03 libraries."""
26 changes: 18 additions & 8 deletions day03/lib/classes.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
"""Day3 classes."""
import re
from dataclasses import dataclass

Expand All @@ -7,13 +8,15 @@

@dataclass
class PartNumber:
"""Class respresenting a potential part number, and its position."""

col: int
row: int
length: int
value: int

def touching(self, col: int, row: int, row_size: int) -> bool:
"""Returns if a given coordinate is touching this PartNumber"""
"""Returns if a given coordinate is touching this PartNumber."""
start_x = max(0, self.col - 1)
end_x = min(self.end_index, row_size)

Expand All @@ -25,19 +28,22 @@ def touching(self, col: int, row: int, row_size: int) -> bool:

@property
def end_index(self) -> int:
"""Returns the end column index of the number."""
return self.col + self.length


@dataclass
class Gear:
"""Class representing a potential gear (``*`` icon)."""

col: int
row: int

part_numbers: list[PartNumber] | None = None

@property
def gear_ratio(self) -> int:
"""If we have exactly two parts, returns the gear ratio"""
"""If we have exactly two parts, returns the gear ratio."""
if self.part_numbers is None:
raise ValueError("self.part_numbers not initialized")
if len(self.part_numbers) == 2:
Expand All @@ -47,18 +53,22 @@ def gear_ratio(self) -> int:

@dataclass
class Matrix:
"""Represents the entire 2d array."""

data: list[str]

@property
def row_size(self) -> int:
"""How long each row is."""
return len(self.data[0])

@property
def row_count(self) -> int:
"""How many rows there are."""
return len(self.data)

def get_part_numbers(self) -> list[PartNumber]:
"""Retrieve numbered words like 456 from the matrix"""
"""Retrieve numbered words like 456 from the matrix."""
results = []

for row, line in enumerate(self.data):
Expand All @@ -74,11 +84,11 @@ def get_part_numbers(self) -> list[PartNumber]:

@staticmethod
def is_engine_part_row(row: str) -> bool:
"""Returns if there is an engine part in this row"""
"""Returns if there is an engine part in this row."""
return any(char not in NON_PART for char in row)

def is_engine_part(self, part_number: PartNumber) -> bool:
"""Return whether a part_number is an engine part by looking at its surroundings"""
"""Return whether a part_number is an engine part by looking at its surroundings."""
start_x = max(0, part_number.col - 1)
end_x = min(part_number.end_index + 1, self.row_size)

Expand Down Expand Up @@ -106,7 +116,7 @@ def is_engine_part(self, part_number: PartNumber) -> bool:
return False

def get_gears(self, part_numbers: list[PartNumber]) -> list[Gear]:
"""Retrieve gears from the matrix"""
"""Retrieve gears from the matrix."""
results = []
for row, line in enumerate(self.data):
for col, char in enumerate(line):
Expand All @@ -119,13 +129,13 @@ def get_gears(self, part_numbers: list[PartNumber]) -> list[Gear]:
def find_gear_parts(
self, gear: Gear, part_numbers: list[PartNumber]
) -> list[PartNumber]:
"""Returns a list of part_numbers that are touching a given gear"""
"""Returns a list of part_numbers that are touching a given gear."""
result = []
for part_number in part_numbers:
if part_number.touching(gear.col, gear.row, self.row_size):
result.append(part_number)
return result

def filter_engine_parts(self, part_numbers: list[PartNumber]) -> list[PartNumber]:
"""Return the legit part numbers"""
"""Return the legit part numbers."""
return list(filter(self.is_engine_part, part_numbers))
3 changes: 2 additions & 1 deletion day03/lib/parsers.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
"""Functions to parse from a file into well defined classes."""
from day03.lib.classes import Matrix


def get_matrix(path: str) -> Matrix:
"""Convert text file to matrix"""
"""Convert text file to matrix."""
with open(path, "r", encoding="utf8") as file:
data = file.readlines()
data = [line.strip() for line in data]
Expand Down
6 changes: 6 additions & 0 deletions day03/tests/test_classes.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
"""tests day3's classes."""
from dataclasses import dataclass

import pytest
Expand All @@ -9,13 +10,16 @@

@dataclass
class PartNumberTouchTest:
"""Result for a part number touching something else."""

col: int
row: int
row_size: int
result: bool


def test_part_number() -> None:
"""Tests part number class."""
part_number = PartNumber(0, 0, 3, 467)

assert part_number.end_index == 3
Expand All @@ -40,6 +44,7 @@ def test_part_number() -> None:


def test_matrix() -> None:
"""Tests matrix."""
matrix: Matrix = get_matrix(INPUT_SMALL)
part_numbers: list["PartNumber"] = matrix.get_part_numbers()
assert (matrix.row_count, matrix.row_size) == (10, 10)
Expand All @@ -60,6 +65,7 @@ def test_matrix() -> None:


def test_gear() -> None:
"""Tests gear class."""
# 69...
# ..*78
# 54...
Expand Down
3 changes: 3 additions & 0 deletions day03/tests/test_day3.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
"""test day3 main functions."""
from typing import TYPE_CHECKING

from day03.day3 import INPUT_SMALL, part1, part2
Expand All @@ -8,13 +9,15 @@


def test_part1() -> None:
"""Test part1."""
matrix: Matrix = get_matrix(INPUT_SMALL)
part_numbers: list[PartNumber] = matrix.get_part_numbers()
part_numbers = matrix.filter_engine_parts(part_numbers)
assert part1(part_numbers) == 4361


def test_part2() -> None:
"""Test part2."""
matrix: Matrix = get_matrix(INPUT_SMALL)
part_numbers: list[PartNumber] = matrix.get_part_numbers()
part_numbers = matrix.filter_engine_parts(part_numbers)
Expand Down

0 comments on commit 68a5a9f

Please sign in to comment.