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.
115 lines
2.6 KiB
115 lines
2.6 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;
|
|
};
|
|
|
|
auto parse_input(char *file)
|
|
{
|
|
ifstream input(file);
|
|
if (!input.is_open()) exit(1);
|
|
|
|
struct 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(struct 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(struct 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)
|
|
{
|
|
unsigned lowpoints = 0;
|
|
|
|
for (unsigned y = 0; y < input.height; y++) {
|
|
for (unsigned x = 0; x < input.width; x++) {
|
|
if (is_lowest(input, y, x)) {
|
|
char height = getpoint2d(input, y, x);
|
|
lowpoints += height + 1;
|
|
}
|
|
}
|
|
}
|
|
|
|
return lowpoints;
|
|
}
|
|
|
|
unsigned recurse_basin(struct 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;
|
|
}
|
|
|
|
unsigned part2(auto input)
|
|
{
|
|
unsigned biggest[4] = {0};
|
|
|
|
for (unsigned y = 0; y < input.height; y++) {
|
|
for (unsigned x = 0; x < input.width; x++) {
|
|
unordered_set<unsigned> basin;
|
|
biggest[0] = recurse_basin(input, basin, y, x);
|
|
sort(biggest, biggest + 4);
|
|
}
|
|
}
|
|
|
|
return biggest[1] * biggest[2] * biggest[3];
|
|
}
|
|
|
|
int main(int argc, char *argv[])
|
|
{
|
|
if (argc <= 1) return 1;
|
|
auto input = parse_input(argv[1]);
|
|
|
|
cout << part1(input) << endl;
|
|
cout << part2(input) << endl;
|
|
}
|
|
|