Skip to content

Commit 46016fd

Browse files
author
Mallory Brickerd
committed
feat: aoc 2025 day 2 solution + tests
1 parent da7dc7f commit 46016fd

File tree

4 files changed

+126
-0
lines changed

4 files changed

+126
-0
lines changed

_2025/solutions/day02.py

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
"""Boilerplate solution template for Advent of Code daily challenges.
2+
3+
This module provides a template class for solving Advent of Code puzzle problems.
4+
It includes a base structure with two method stubs (part1 and part2) that can be
5+
implemented for specific day's challenges.
6+
7+
The template follows the SolutionBase pattern used across the Advent of Code solutions,
8+
allowing for consistent handling of input parsing and solution execution.
9+
"""
10+
11+
from functools import partial
12+
from typing import Callable
13+
14+
from aoc.models.base import SolutionBase
15+
16+
17+
class Solution(SolutionBase):
18+
"""Solution template for Advent of Code daily puzzle.
19+
20+
This class provides a standardized structure for implementing solutions to
21+
daily Advent of Code challenges. It inherits from SolutionBase and includes
22+
method stubs for part1 and part2 of the puzzle.
23+
24+
Subclasses should override these methods with specific implementation logic
25+
for parsing input and solving the puzzle requirements.
26+
"""
27+
28+
def has_repeated_sequence(self, n: int, num_repeats: int = None) -> bool:
29+
s = str(n)
30+
length = len(s)
31+
32+
if num_repeats:
33+
if num_repeats <= 1:
34+
return False
35+
36+
if length % num_repeats != 0:
37+
return False
38+
39+
size = length // num_repeats
40+
return s == s[:size] * num_repeats
41+
42+
else: # Check for any number of repetitions > 1
43+
for k in range(2, length + 1):
44+
if length % k == 0:
45+
size = length // k
46+
if s == s[:size] * k:
47+
return True
48+
49+
return False
50+
51+
def solve_part(self, data: list[str], func: Callable) -> int:
52+
"""Calculates the sum of numbers in ranges that satisfy the check_func."""
53+
invalid = 0
54+
for line in data[0].split(","):
55+
start, end = map(int, line.split("-"))
56+
for product in range(start, end + 1):
57+
if func(product):
58+
invalid += product
59+
60+
return invalid
61+
62+
def part1(self, data: list[str]) -> int:
63+
"""Solve the first part of the daily puzzle.
64+
65+
Args:
66+
data: List of input strings to be processed
67+
68+
Returns
69+
-------
70+
int: Solution for part 1 of the puzzle
71+
"""
72+
check_for_two_repeats = partial(self.has_repeated_sequence, num_repeats=2)
73+
return self.solve_part(data, check_for_two_repeats)
74+
75+
def part2(self, data: list[str]) -> int:
76+
"""Solve the second part of the daily puzzle.
77+
78+
Args:
79+
data: List of input strings to be processed
80+
81+
Returns
82+
-------
83+
int: Solution for part 2 of the puzzle
84+
"""
85+
return self.solve_part(data, self.has_repeated_sequence)
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
11-22,95-115,998-1012,1188511880-1188511890,222220-222224,1698522-1698528,446443-446449,38593856-38593862,565653-565659,824824821-824824827,2121212118-2121212124
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
11-22,95-115,998-1012,1188511880-1188511890,222220-222224,1698522-1698528,446443-446449,38593856-38593862,565653-565659,824824821-824824827,2121212118-2121212124

_2025/tests/test_02.py

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
"""Test suite for Advent of Code daily challenge solution.
2+
3+
This module contains the test cases for the solution to the Advent of Code
4+
daily puzzle. It uses the TestSolutionUtility to run tests for both parts
5+
of the challenge.
6+
7+
The template provides a structure for defining tests for a specific day's
8+
solution, ensuring that the implementation meets the expected outputs for
9+
given test inputs.
10+
"""
11+
from aoc.models.tester import TestSolutionUtility
12+
13+
def test_day02_part1() -> None:
14+
"""Test the solution for Part 1 of the daily puzzle.
15+
16+
This test runs the solution for Part 1 of the puzzle against the
17+
provided test input and compares the result with the expected output.
18+
"""
19+
TestSolutionUtility.run_test(
20+
year=2025,
21+
day=2,
22+
is_raw=False,
23+
part_num=1,
24+
expected=1227775554,
25+
)
26+
27+
def test_day02_part2() -> None:
28+
"""Test the solution for Part 2 of the daily puzzle.
29+
30+
This test runs the solution for Part 2 of the puzzle against the
31+
provided test input and compares the result with the expected output.
32+
"""
33+
TestSolutionUtility.run_test(
34+
year=2025,
35+
day=2,
36+
is_raw=False,
37+
part_num=2,
38+
expected=4174379265,
39+
)

0 commit comments

Comments
 (0)