Spoiler alert

This is a full solution for Advent of Code 2025, day 12 puzzles with explanations.

If you want to try to solve it yourself first, head over to https://adventofcode.com/2025/day/12 and give it a go and then come back and compare notes.

You can find the full code at https://github.com/Hamatti/adventofcode-2025/blob/main/src/day_12.py

We’ve reached the end of this year’s Advent of Code. Jumping into a ventilation duct (and yes, Die Hard is a Christmas movie) leads us to to a cavern full of Christmas trees and presents to be distributed under the trees for local Elves.

Read input

We have a multisection input with first section being different presents and the latter section being information about trees

0:
###
##.
##.

1:
###
##.
.##

2:
.##
###
##.

3:
##.
###
##.

4:
###
#..
###

5:
###
.#.
###

4x4: 0 0 0 0 2 0
12x5: 1 0 1 0 2 2
12x5: 1 0 1 0 3 2

Let’s start by figuring out how to read in the presents. I decided to start with a sparse grid as that seemed appropriate. This time, I’m only storing the coordinates in a set rather than a dict as the content doesn’t matter.

from collections import namedtuple
 
Present = namedtuple('Present', ['area', 'coordinates'])
 
def present_mapper(section: str) -> Present:
    lines = section.split('\n')[1:]
    coordinates: set[Coordinate] = set()
    for y in range(0, len(lines)):
        for x in range(0, len(lines[0])):
            if lines[y][x] == '#':
                coordinates.add(Coordinate(x=x, y=y))
    return Present(len(coordinates), coordinates)

To finish up a present, I’m storing it and its size in a namedtuple.

Then, for the second half, we model the trees.

from collections import namedtuple
 
Tree = namedtuple('Tree', ['width', 'height', 'presents', 'area'])
 
def trees_mapper(section: str) -> List[Tree]:
    trees = []
    for line in section.split('\n'):
        size, presents = line.split(': ')
        size = size.split('x')
        width, height = int(size[0]), int(size[1])
        presents = [int(p) for p in presents.split(' ')]
        trees.append(Tree(width, height, presents, width * height))
    return trees

Part 1

In the first part, we need to check how many of these tree+present combinations actually fit.

This is the type of puzzle, maybe in jest, where all my good teachings go out of the window. I usually teach to first solve with the example input and only then go into the main one. Today, there seems to have been a twist where the example input solution is very complex and the real input is trivial.

Apparently, all you need to do is check if the area provided is large enough to hold all the presents. No need to worry about any rotations or geometry or placing presents in particular arraignments.

def part_1() -> int:
    data = read_multisection_input(12, [present_mapper] * 6 + [trees_mapper])
    presents = data[:-1]
    trees = data[-1]
    
    valid_trees = 0
 
    for tree in trees:
        area_needed = 0
        for index, count in enumerate(tree.presents):
            area_needed += count * presents[index].area
        if tree.area >= area_needed:
            valid_trees += 1
    
    return valid_trees

So for each tree, we calculate how much space do the presents required need and if that is smaller than or equal to available space, it’s a good tree.

Part 2

In a classic Advent of Code manner, the last star is about gathering all 23 stars before it. Once you’ve done that, you get to press a button and Christmas is saved.

It was a lovely journey once again and I got to talk about puzzles and Python with so many wonderful people online and offline. Thanks for being part of that journey — Merry Christmas and happy holidays ❤️!

For the first time, I get to admire the fully revealed calendar art and it’s beautiful.

A completed, colorful ASCII art of Advent of Code calendar depicting an underground building with different floors and rooms.

Get in touch

If you want to comment on these solutions, I share them in Mastodon where you can look for the post for the right date or you can start a discussion over email with juhamattisantala@gmail.com.

Follow via RSS

I have created a custom RSS feed for these solutions so you can follow along and not miss any of them!