From 68a5a9fd2e434c4dc7c7f750d57ce75c900b52df Mon Sep 17 00:00:00 2001 From: alexo Date: Sat, 30 Dec 2023 00:03:33 +1100 Subject: [PATCH] docs: day03 --- day03/day3.py | 6 ++++-- day03/lib/__init__.py | 2 +- day03/lib/classes.py | 26 ++++++++++++++++++-------- day03/lib/parsers.py | 3 ++- day03/tests/test_classes.py | 6 ++++++ day03/tests/test_day3.py | 3 +++ 6 files changed, 34 insertions(+), 12 deletions(-) diff --git a/day03/day3.py b/day03/day3.py index 6bfa8ad..78f702b 100644 --- a/day03/day3.py +++ b/day03/day3.py @@ -1,5 +1,4 @@ -"""Day 3 implementation -""" +"""Day 3 implementation.""" from day03.lib.classes import Gear, Matrix, PartNumber @@ -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) diff --git a/day03/lib/__init__.py b/day03/lib/__init__.py index 5950102..30bac72 100644 --- a/day03/lib/__init__.py +++ b/day03/lib/__init__.py @@ -1 +1 @@ -"""day03 classes.""" +"""day03 libraries.""" diff --git a/day03/lib/classes.py b/day03/lib/classes.py index a704303..7005233 100644 --- a/day03/lib/classes.py +++ b/day03/lib/classes.py @@ -1,3 +1,4 @@ +"""Day3 classes.""" import re from dataclasses import dataclass @@ -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) @@ -25,11 +28,14 @@ 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 @@ -37,7 +43,7 @@ class Gear: @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: @@ -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): @@ -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) @@ -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): @@ -119,7 +129,7 @@ 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): @@ -127,5 +137,5 @@ def find_gear_parts( 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)) diff --git a/day03/lib/parsers.py b/day03/lib/parsers.py index c6f90ff..3dadb10 100644 --- a/day03/lib/parsers.py +++ b/day03/lib/parsers.py @@ -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] diff --git a/day03/tests/test_classes.py b/day03/tests/test_classes.py index 01eb0a8..ffbdd0b 100644 --- a/day03/tests/test_classes.py +++ b/day03/tests/test_classes.py @@ -1,3 +1,4 @@ +"""tests day3's classes.""" from dataclasses import dataclass import pytest @@ -9,6 +10,8 @@ @dataclass class PartNumberTouchTest: + """Result for a part number touching something else.""" + col: int row: int row_size: int @@ -16,6 +19,7 @@ class PartNumberTouchTest: def test_part_number() -> None: + """Tests part number class.""" part_number = PartNumber(0, 0, 3, 467) assert part_number.end_index == 3 @@ -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) @@ -60,6 +65,7 @@ def test_matrix() -> None: def test_gear() -> None: + """Tests gear class.""" # 69... # ..*78 # 54... diff --git a/day03/tests/test_day3.py b/day03/tests/test_day3.py index 261f9c8..7b24199 100644 --- a/day03/tests/test_day3.py +++ b/day03/tests/test_day3.py @@ -1,3 +1,4 @@ +"""test day3 main functions.""" from typing import TYPE_CHECKING from day03.day3 import INPUT_SMALL, part1, part2 @@ -8,6 +9,7 @@ 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) @@ -15,6 +17,7 @@ def test_part1() -> None: 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)