#include #include #include #include using namespace std; #define getmap2d(a) ((char(*)[a.width])a.arr.data()) struct map2d { vector 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 & 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 & 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 lowpoints) { unsigned biggest[4] = {0}; for (coord2d coord : lowpoints) { unordered_set 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 lowpoints; cout << part1(input, lowpoints) << endl; cout << part2(input, lowpoints) << endl; }