Advent of Code 2021, see plus plus edition
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

123 lines
2.8 KiB

#include <iostream>
#include <fstream>
#include <vector>
#include <unordered_set>
using namespace std;
#define getmap2d(a) ((char(*)[a.width])a.arr.data())
struct map2d {
vector<char> arr;
unsigned width;
unsigned height;
};
struct coord2d {
int y;
int x;
};
auto parse_input(char *file)
{
ifstream input(file);
if (!input.is_open()) exit(1);
map2d map;
unsigned width = 0;
for (string line; getline(input, line);) {
if (!width) width = line.size();
if (width != line.size()) exit(1);
for (char c : line) {
map.arr.push_back(c - '0');
}
}
map.width = width;
map.height = map.arr.size() / width;
return map;
}
char getpoint2d(map2d & input, int y, int x)
{
auto map = getmap2d(input);
if (y < 0 || x < 0) return 9;
if ((unsigned)y >= input.height || (unsigned)x >= input.width) return 9;
return map[y][x];
}
int surr[][2] = {
{-1, 0},
{ 0, -1}, { 0, 1},
{ 1, 0},
};
bool is_lowest(map2d & input, int y, int x)
{
char base = getpoint2d(input, y, x);
for (int i = 0; i < 4; i++) {
char cmp = getpoint2d(input, y + surr[i][0], x + surr[i][1]);
if (cmp <= base) return false;
}
return true;
}
unsigned part1(auto input, vector<coord2d> & lowpoints)
{
for (unsigned y = 0; y < input.height; y++) {
for (unsigned x = 0; x < input.width; x++) {
if (is_lowest(input, y, x)) {
coord2d coord = {(int)y, (int)x};
lowpoints.push_back(coord);
}
}
}
auto map = getmap2d(input);
unsigned total = 0;
for (coord2d coord : lowpoints) {
total += map[coord.y][coord.x] + 1;
}
return total;
}
unsigned recurse_basin(map2d & input, unordered_set<unsigned> & basin, int y, int x)
{
if (basin.contains(y * input.width + x)) return 0;
basin.insert(y * input.width + x);
unsigned size = 1;
char base = getpoint2d(input, y, x);
for (int i = 0; i < 4; i++) {
int new_y = y + surr[i][0];
int new_x = x + surr[i][1];
char cmp = getpoint2d(input, new_y, new_x);
if (cmp >= 9) continue;
if (cmp >= base) size += recurse_basin(input, basin, new_y, new_x);
}
return size;
}
uint64_t part2(auto input, vector<coord2d> lowpoints)
{
unsigned biggest[4] = {0};
for (coord2d coord : lowpoints) {
unordered_set<unsigned> basin;
biggest[0] = recurse_basin(input, basin, coord.y, coord.x);
sort(biggest, biggest + 4);
}
return (uint64_t)biggest[1] * biggest[2] * biggest[3];
}
int main(int argc, char *argv[])
{
if (argc <= 1) return 1;
auto input = parse_input(argv[1]);
vector<coord2d> lowpoints;
cout << part1(input, lowpoints) << endl;
cout << part2(input, lowpoints) << endl;
}