DEV Community

Cover image for Advent of Code 2025 - December 4th
Rob van der Leek
Rob van der Leek

Posted on

Advent of Code 2025 - December 4th

In this series, I'll share my progress with the 2025 version of Advent of Code.

Check the first post for a short intro to this series.

You can also follow my progress on GitHub.

December 4th

The puzzle of day 4 was pretty straightforward. I guess it's possible to use a single pass, instead of an iterative approach, but I did not have the time to look into that.

My pitfall for this puzzle: The C++ std::string::substr method takes a start and length argument. Who would have known?! I expected a start and non-inclusive end argument. That took me some debug headaches 🤯

Solution here, do not click if you want to solve the puzzle first yourself
#include <cassert>
#include <fstream>
#include <iostream>
#include <sstream>


std::vector<std::string> loadInput(const std::string &filename) {
    std::vector<std::string> result;
    std::ifstream file(filename);
    std::string line;
    while (std::getline(file, line)) {
        result.push_back(line);
    }
    return result;
}

bool canAccess(const std::vector<std::string> &grid, int row, int col) {
    int rolls = 0;
    std::stringstream ss;
    if (row > 0) {
        const std::string &topRow = grid[row - 1];
        ss << topRow.substr(std::max(0, col - 1), col == 0 ? 2 : 3);
    }
    ss << grid[row].substr(std::max(0, col - 1), col == 0 ? 2 : 3);
    if (row < grid.size() - 1) {
        const std::string &bottomRow = grid[row + 1];
        ss << bottomRow.substr(std::max(0, col - 1), col == 0 ? 2 : 3);
    }
    const std::string neighborsStr = ss.str();
    for (const char c : neighborsStr) {
        if (c == '@') {
            rolls++;
        }
    }
    return rolls - 1 /* self */ < 4;
}

std::vector<std::string> processGrid(std::vector<std::string> &grid) {
    std::vector<std::string> result;
    for (int rowIdx = 0; rowIdx < grid.size(); ++rowIdx) {
        std::string row = grid[rowIdx];
        std::string nextRow = row;
        for (int colIdx = 0; colIdx < row.length(); ++colIdx) {
            auto element = row[colIdx];
            if (element == '@' && canAccess(grid, rowIdx, colIdx)) {
                nextRow[colIdx] = '.';
                grid[rowIdx] = row;
            }
        }
        result.push_back(nextRow);
    }
    return result;
}

int countGrid(std::vector<std::string> &grid) {
    int result = 0;
    for (int rowIdx = 0; rowIdx < grid.size(); ++rowIdx) {
        for (int colIdx = 0; colIdx < grid[rowIdx].length(); ++colIdx) {
            if (grid[rowIdx][colIdx] == '@') {
                ;
                result++;
            }
        }
    }
    return result;
}

void partOne() {
    auto grid = loadInput("/Users/rob/projects/robvanderleek/adventofcode/2025/04/input.txt");
    auto startCount = countGrid(grid);
    auto nextGrid = processGrid(grid);
    auto nextCount = countGrid(nextGrid);
    int result = startCount - nextCount;
    std::cout << result << std::endl;
    assert(result == 1495);
}

void partTwo() {
    auto grid = loadInput("/Users/rob/projects/robvanderleek/adventofcode/2025/04/input.txt");
    auto startCount = countGrid(grid);
    auto nextGrid = processGrid(grid);
    auto previousCount = startCount;
    auto nextCount = countGrid(nextGrid);
    while (nextCount < previousCount) {
        previousCount = nextCount;
        nextGrid = processGrid(nextGrid);
        nextCount = countGrid(nextGrid);
    }
    long result = startCount - nextCount;
    std::cout << result << std::endl;
    assert(result == 8768);
}

int main() {
    partOne();
    partTwo();
    return 0;
}
Enter fullscreen mode Exit fullscreen mode

That's it! See you again tomorrow!

Top comments (0)