Skip to content

Commit f87d2fd

Browse files
committed
feat: aoc 2025 day 3 solution + tests
1 parent 4c517df commit f87d2fd

File tree

5 files changed

+140
-1
lines changed

5 files changed

+140
-1
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# Advent of Code
1+
# Advent of Code - Python
22

33
A modular Python framework for efficiently tackling Advent of Code challenges, designed for clarity, quality, and easy setup. The repository supports day-by-day workflows for solving, testing, and submitting solutions, with strong emphasis on reproducible results and consistent code standards.
44

_2025/solutions/day03.py

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
"""Day 3: Maximum Joltage Extraction
2+
3+
This module provides the solution for Advent of Code 2025 - Day 3.
4+
5+
It finds the maximum numeric value that can be formed by selecting k digits
6+
from a string while maintaining their original order.
7+
8+
The module contains a Solution class that inherits from SolutionBase for
9+
extracting optimal digit sequences from power bank readings.
10+
"""
11+
12+
from aoc.models.base import SolutionBase
13+
14+
15+
class Solution(SolutionBase):
16+
"""Extract maximum joltage values from digit sequences.
17+
18+
This solution finds the largest k-digit number that can be formed from
19+
a string of digits while preserving their original order. Part 1 extracts
20+
2-digit values, while Part 2 extracts 12-digit values. Uses a greedy
21+
monotonic stack algorithm for optimal digit selection.
22+
23+
The algorithm ensures maximum value by keeping larger digits when possible
24+
and removing smaller preceding digits when necessary.
25+
"""
26+
27+
def find_max_joltage(self, bank: str, k: int) -> int:
28+
"""Find maximum k-digit number from digit string preserving order.
29+
30+
Uses a monotonic decreasing stack to greedily select the k largest
31+
digits while maintaining their relative order. Removes digits that
32+
would prevent forming a larger number.
33+
34+
Args:
35+
bank: String of digits representing power bank reading
36+
k: Number of digits to select for the output value
37+
38+
Returns
39+
-------
40+
int: Maximum k-digit number that can be formed from the input digits
41+
while preserving their original order
42+
"""
43+
digits = [int(c) for c in bank]
44+
n = len(digits)
45+
remove = n - k
46+
stack: list[int] = []
47+
48+
for d in digits:
49+
while remove > 0 and stack and stack[-1] < d:
50+
stack.pop()
51+
remove -= 1
52+
53+
stack.append(d)
54+
55+
if remove > 0:
56+
stack = stack[:-remove]
57+
58+
value = 0
59+
for d in stack[:k]:
60+
value = value * 10 + d
61+
62+
return value
63+
64+
def part1(self, data: list[str]) -> int:
65+
"""Calculate sum of maximum 2-digit joltages from all power banks.
66+
67+
Each power bank reading is a string of digits. Extracts the maximum
68+
2-digit number from each reading (preserving digit order) and returns
69+
the sum of all such values.
70+
71+
Args:
72+
data: List of power bank readings (digit strings)
73+
74+
Returns
75+
-------
76+
int: Sum of maximum 2-digit values from all readings
77+
"""
78+
return sum([self.find_max_joltage(line, 2) for line in data])
79+
80+
def part2(self, data: list[str]) -> int:
81+
"""Calculate sum of maximum 12-digit joltages from all power banks.
82+
83+
Each power bank reading is a string of digits. Extracts the maximum
84+
12-digit number from each reading (preserving digit order) and returns
85+
the sum of all such values.
86+
87+
Args:
88+
data: List of power bank readings (digit strings)
89+
90+
Returns
91+
-------
92+
int: Sum of maximum 12-digit values from all readings
93+
"""
94+
return sum([self.find_max_joltage(line, 12) for line in data])
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
987654321111111
2+
811111111111119
3+
234234234234278
4+
818181911112111
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
987654321111111
2+
811111111111119
3+
234234234234278
4+
818181911112111

_2025/tests/test_03.py

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
"""Test suite for Day 3: Maximum Joltage Extraction
2+
3+
This module contains tests for the Day 3 solution, which extracts maximum
4+
numeric values from digit sequences while preserving order. The tests verify:
5+
6+
1. Part 1: Sum of maximum 2-digit values from all power bank readings
7+
2. Part 2: Sum of maximum 12-digit values from all power bank readings
8+
"""
9+
from aoc.models.tester import TestSolutionUtility
10+
11+
def test_day03_part1() -> None:
12+
"""Test extracting and summing maximum 2-digit joltage values.
13+
14+
This test runs the solution for Part 1 of the puzzle against the
15+
provided test input and compares the result with the expected output.
16+
"""
17+
TestSolutionUtility.run_test(
18+
year=2025,
19+
day=3,
20+
is_raw=False,
21+
part_num=1,
22+
expected=357,
23+
)
24+
25+
def test_day03_part2() -> None:
26+
"""Test extracting and summing maximum 12-digit joltage values.
27+
28+
This test runs the solution for Part 2 of the puzzle against the
29+
provided test input and compares the result with the expected output.
30+
"""
31+
TestSolutionUtility.run_test(
32+
year=2025,
33+
day=3,
34+
is_raw=False,
35+
part_num=2,
36+
expected=3121910778619,
37+
)

0 commit comments

Comments
 (0)