--- Day 9: Smokey ---

December 9

Listening to: My partner playing Halo Infinite in the other room


I swear, there's going to be a puzzle soon that's some sort of maze solving. Entering a cave, going through lava tubes. It's gotta be coming soon. There's even dealing with a 2d map of sorts for this one, it's all just being set up!

This one doesn't seem so bad. It's a 2d array of numbers. It spends some time defining low points, but it can be boiled down to: points that are less than all neighbors. 2-4 comparisons. Not so bad.

int totalRisk = 0;

for (int x = 0; x < map.size(); x++)
for (int y = 0; y < map[x].size(); y++) {
    int c = map[x][y];
    if (y > 0               && c >= map[x][y-1]) continue; // Left
    if (x > 0               && c >= map[x-1][y]) continue; // Up
    if (y < map[x].size()-1 && c >= map[x][y+1]) continue; // Right
    if (x < map.size()-1    && c >= map[x+1][y]) continue; // Down
    totalRisk += 1 + map[x][y];
}

Not bad, but I'll admit it took me a couple tries to get the logic juuust right. A little trial and error doesn't hurt. It's faster to just try a few different iterations than just stare at it and think through it. If there's only a few iterations possible anyway.


I figured this would be the extension. I think I did a problem similar to this once. In a 2D array of bools (basically, a bitmap), find the largest continuous blob; rather, the largest area of adjacent 1s. This feels very similar.

In fact, it's exactly the same problem in disguise. All 9s are not part of a 'basin', while the rest of the digits are. I don't need to process any digits beyond 'is this digit a 9'. And as an extra boon, from part 1, I have a list of the 'center' of each basin as well. At least that's my assumption. I'm going to work with that assumption.

vector<int> sizes;
for (auto lowPoint: lowPoints) {
    queue<pair<int, int>> searchQueue;
    searchQueue.push(lowPoint);

    int basinSize = 0;
    while (!searchQueue.empty()) {
        pair<int, int> p = searchQueue.front();
        searchQueue.pop();

        // Ignore maxheight (9), and already searched (-1)
        if (map[p.first][p.second] == 9 || map[p.first][p.second] == -1) continue;

        basinSize++;
        map[p.first][p.second] = -1;

        // Enqueue next adjacencies
        if (p.first > 0)                searchQueue.push(pair<int, int>(p.first-1, p.second));
        if (p.second > 0)               searchQueue.push(pair<int, int>(p.first, p.second-1));
        if (p.first < map.size()-1)     searchQueue.push(pair<int, int>(p.first+1, p.second));
        if (p.second < map[0].size()-1) searchQueue.push(pair<int, int>(p.first, p.second+1));
    }
    cout << "Basin: " << basinSize << endl;
    sizes.push_back(basinSize);
}

Okay, one thing that's bothering me with this solution, ultimately. It wouldn't be unheard of to have a basin with two low points, using this notation.

92329
71212
92329

This has two low points in the middle, but by the definition laid out, is a single basin. I think. There's not really a good deliniation point between the two. But, that would complicate things in a way that might make it too difficult, at least for this point in the list of puzzles.


My solutions for today's puzzles