Skip to content

Commit 0c9792c

Browse files
committed
feat: aoc 2025 day 12 solution + tests
1 parent 79763a9 commit 0c9792c

File tree

3 files changed

+145
-0
lines changed

3 files changed

+145
-0
lines changed

_2025/solutions/day12.py

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
"""Day 12: Christmas Tree Farm
2+
3+
This module provides the solution for Advent of Code 2025 - Day 12.
4+
5+
The input describes oddly-shaped presents and the rectangular regions
6+
under Christmas trees where those presents need to fit.
7+
8+
This implementation uses a simplified feasibility check: it parses all
9+
present shapes, then for each region computes how much area the listed
10+
presents would require and compares it against the region area.
11+
"""
12+
13+
from aoc.models.base import SolutionBase
14+
15+
16+
class Solution(SolutionBase):
17+
"""Check which tree regions are large enough for their present lists.
18+
19+
The puzzle input is split into two sections separated by a blank line:
20+
21+
- The first section lists present shapes, each starting with an index
22+
line (`0:`, `1:`, ...) followed by a small ASCII-art block of `#`
23+
and `.` characters.
24+
- The second section lists regions in the form `WxH: c0 c1 c2 ...`,
25+
where each `ci` is the count of presents of shape i to place.
26+
27+
This implementation only uses the region dimensions and the counts
28+
of presents to compute a required area per region and checks whether
29+
the available area is sufficient.
30+
"""
31+
32+
def part1(self, data: str) -> int:
33+
"""Count how many regions can fit all of their requested presents.
34+
35+
The raw input is split on blank lines. All blocks except the last
36+
are interpreted as shape definitions; the final block contains the
37+
region lines. For each region line of the form:
38+
39+
WxH: n0 n1 n2 ...
40+
41+
it computes a required area of `8 * sum(ni)` and compares it to
42+
`width * height`. If the region has at least this much area, it
43+
is counted as able to fit all presents.
44+
45+
Args:
46+
data: Full puzzle input as a single string.
47+
48+
Returns
49+
-------
50+
int: Number of regions that can fit all of their listed presents.
51+
"""
52+
*shape_blocks, regions = data.split("\n\n")
53+
54+
shapes: list[str] = []
55+
for block in shape_blocks:
56+
lines = block.split("\n")
57+
body = "\n".join(lines[1:])
58+
shapes.append(body)
59+
60+
count = 0
61+
for region in regions.split("\n"):
62+
region = region.strip()
63+
if not region:
64+
continue
65+
66+
width, height, *nums = map(int, region.replace("x", " ").replace(":", "").split())
67+
required = 8 * sum(nums)
68+
if width * height >= required:
69+
count += 1
70+
71+
return count
72+
73+
def part2(self, data: str) -> str:
74+
"""Return a festive message after evaluating all regions.
75+
76+
Part 2 of this solution does not perform additional computation
77+
on the input; instead, it simply returns a celebratory string to
78+
mark the completion of the Advent of Code event.
79+
80+
Args:
81+
data: Full puzzle input as a single string.
82+
83+
Returns
84+
-------
85+
str: Festive completion message.
86+
"""
87+
return "Merry Christmas!"
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
0:
2+
###
3+
##.
4+
##.
5+
6+
1:
7+
###
8+
##.
9+
.##
10+
11+
2:
12+
.##
13+
###
14+
##.
15+
16+
3:
17+
##.
18+
###
19+
##.
20+
21+
4:
22+
###
23+
#..
24+
###
25+
26+
5:
27+
###
28+
.#.
29+
###
30+
31+
4x4: 0 0 0 0 2 0
32+
12x5: 1 0 1 0 2 2
33+
12x5: 1 0 1 0 3 2

_2025/tests/test_12.py

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
"""Test suite for Day 12: Christmas Tree Farm
2+
3+
This module contains tests for the Day 12 solution, which checks for
4+
each rectangular region under a Christmas tree whether it can fit all
5+
requested oddly-shaped presents. The tests verify:
6+
7+
1. Part 1: Counting how many regions can fit their listed presents
8+
"""
9+
10+
from aoc.models.tester import TestSolutionUtility
11+
12+
13+
def test_day12_part1() -> None:
14+
"""Test counting regions that can fit all presents.
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=12,
22+
is_raw=True,
23+
part_num=1,
24+
expected=3,
25+
)

0 commit comments

Comments
 (0)