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 1
s. This feels very similar.
In fact, it's exactly the same problem in disguise. All 9
s 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.