Published December 12, 2025
It's day 12, the last day of the 2025 Advent of Code (if you're wondering why it's only 12 days this year please look at the AOC FAQ.) The last day is only a 1 part puzzle. For today's the trick was that you could do all the hard work defined in the problem or you could ignore the test data and just figure out if there was enough space in a given region for all of the presents that belonged there (for the test data you'll get 3 when the answer with all the hard work is 2.) While I didn't know this was going to be the case I had a feeling it might be so I went ahead and coded it like that.
Given that we had 2 types of objects - presents and regions - I dedided I was going to go for an OOP solution today and defined 2 classes,
Present and Region
@dataclass
class Present:
shape: str
@property
def area(self) -> int:
return self.shape.count('#')
class Region:
def __init__(self, definition: str):
width, length, presents = re.match(r'(\d+)x(\d+): ((?:[\d+]\s?)+)', definition).groups()
self.width = int(width)
self.length = int(length)
self.requires = list(map(int, presents.split()))
@property
def area(self) -> int:
return self.width * self.length
def required_area(self, presents: list[Present]) -> int:
return sum(presents[i].area * required for i, required in enumerate(self.requires))
Once I did that and I had all the data organized the solution is, essentially, a one-liner:
sum(region.area >= region.required_area(presents) for region in regions)
As I said, this doesn't work for the test data but it does work for the actual data. I can't guarantee that this will work for everyone's puzzle input but it did for mine and I have seen a few people post on Mastodon that it did for them as well.
Day 12 solution on GitHub
I'm also going to take this opportunity to give my thoughts on AOC 2025. It was a fun year. There were a couple of times where I was on the right track but was missing something that would let me finish the solution, where I needed to seek out other peoples' solutions to find that one missing thing. There was one that was beyond my ability because of the math required for me to do a first principles solution and the total unfamiliarity with libraries that could help me do it. For the most part I was able to come up with solutions on my own, by myself, that solved the puzzles in a not unreasonable amount of time. If memory serves, there is only one solution I have that takes ~1 second to run, and all the rest are significantly faster than that.
I would also like to say that I do appreciate the variety of puzzles that went in this year. It seems to me that each one flexed a different muscle and I don't think there were any repeats. As always, solving these puzzles in a reasonable amount of time is possible with a basic knowledge of algorithms and optimizations. All in all a fun year. I look forward to seeing the puzzles that are laid out next year.