Background

Advent of Code is an annual programming challenge where participants complete daily puzzles. In 2025 there were 12 puzzles from Dec 1st to Dec 12th. It’s a friendly competition and participants can use any programming language and any computing resource to complete.

I completed the challenge normally (repo). Now for bonus points, let’s go for an extra challenge of implementing the solution on a Raspberry Pi Pico.

Raspberry Pi Pico

To make it clear, it’s much easier to solve the puzzle on a regular computer (with an OS!) first. Then the solution and understanding of the problem can be ported to the much more constrained environment.

Raspberry Pi Pico specs

Speaking of constrained, let’s list some of the specs of the hardware we have to working with. For this application the two most important specs are:

  • Dual-core Arm Cortex M0+ processor, flexible clock running up to 133 MHz
  • 264 kB of SRAM, and 2 MB of on-board flash memory

That’s not a lot of processor, but more critically, thats not a lot of RAM. We can always wait longer for a calculation, but not enough RAM means we sometimes need to rethink an algorithm or constantly recalculate something because we can’t afford to store the intermediate results.

Project Settings

The features that I am using are stdio support over USB and C++ code (no RTTI and no exceptions). Also I am going to be using ETL instead of STL as much as possible.

Project Settings

In order to use the stdio communication, we need a program to connect to the terminal. I am using putty on Windows, and really the only configuration is selecting the COM port and setting the baud rate to 115200.

Putty Settings1 Putty Settings2

I/O Programming

For program input, I want something pretty close to the std::getline API. Here is normal C++ for reading from a file;

std::ifstream infile("input.txt");

//getline also optionally takes a delimiter parameter
for (std::string line; std::getline(infile, line);) {
    //parse the line
}

So in our embedded application the following API is developed.

template <size_t n>
bool getline(etl::string<n> &line, char delim = 0)
{
    line.clear();
    int read_char{ 0 };
    while (read_char = getchar(), read_char != EOF && read_char != '\x1A' && read_char != '\n' && read_char != delim) {
        line.append(1, static_cast<char>(read_char));
    }

    //trim \r if windows line endings are sent
    etl::trim_from_right(line, "\r");

    //`\x1A` is used to indicate the end of the file
    if (read_char == EOF || read_char == '\x1A')
        return false;
    return true;
}
using str_line_t = etl::string<31>;

//getline also optionally takes a delimiter input
for (str_line_t line; advt::getline(line);) {

}

Because we are reading the characters from the terminal input, we need a way to indicate that the transmission is finished. The byte 0x1A SUB is a special character used to indicate the end of file and it is inserted as the last character of the text file puzzle inputs.

TestData

On the PC side, the putty utility plink is used to transmit the file.

"C:\Program Files\PuTTY\plink.exe" pi_pico < C:\repos\advent2025_pico\day1\input.txt

For output, just the typical printf function has been used. In the future, it would be nice to wrap this in a interface similar to std::print.

ETL

ETL is used in place of the STL as much as possible. ETL provides many classes with similar APIs to the STL counterparts, but without memory allocation and can be configured to not use exceptions. I instead configured ETL to assert on error.

The ETL configuration is set using the etl_profile.h file.

Because ETL does not do memory allocation, the container capacities need to be set at compile time. Thankfully, with errors enabled, if a container runs out of capacity then the program will assert and halt. Then I can determine if the container size can be increased or if the approach needs to be reworked.

Day 1 Example

This screenshots shows the solution to the day 1 example input.

Day1

Link to the repo.