|
|
@ -12,12 +12,17 @@ struct map2d { |
|
|
|
unsigned height; |
|
|
|
}; |
|
|
|
|
|
|
|
struct coord2d { |
|
|
|
int y; |
|
|
|
int x; |
|
|
|
}; |
|
|
|
|
|
|
|
auto parse_input(char *file) |
|
|
|
{ |
|
|
|
ifstream input(file); |
|
|
|
if (!input.is_open()) exit(1); |
|
|
|
|
|
|
|
struct map2d map; |
|
|
|
map2d map; |
|
|
|
|
|
|
|
unsigned width = 0; |
|
|
|
for (string line; getline(input, line);) { |
|
|
@ -33,7 +38,7 @@ auto parse_input(char *file) |
|
|
|
return map; |
|
|
|
} |
|
|
|
|
|
|
|
char getpoint2d(struct map2d input, int y, int x) |
|
|
|
char getpoint2d(map2d & input, int y, int x) |
|
|
|
{ |
|
|
|
auto map = getmap2d(input); |
|
|
|
if (y < 0 || x < 0) return 9; |
|
|
@ -47,7 +52,7 @@ int surr[][2] = { |
|
|
|
{ 1, 0}, |
|
|
|
}; |
|
|
|
|
|
|
|
bool is_lowest(struct map2d input, int y, int x) |
|
|
|
bool is_lowest(map2d & input, int y, int x) |
|
|
|
{ |
|
|
|
char base = getpoint2d(input, y, x); |
|
|
|
for (int i = 0; i < 4; i++) { |
|
|
@ -57,23 +62,27 @@ bool is_lowest(struct map2d input, int y, int x) |
|
|
|
return true; |
|
|
|
} |
|
|
|
|
|
|
|
unsigned part1(auto input) |
|
|
|
unsigned part1(auto input, vector<coord2d> & lowpoints) |
|
|
|
{ |
|
|
|
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; |
|
|
|
coord2d coord = {(int)y, (int)x}; |
|
|
|
lowpoints.push_back(coord); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
return lowpoints; |
|
|
|
auto map = getmap2d(input); |
|
|
|
unsigned total = 0; |
|
|
|
for (coord2d coord : lowpoints) { |
|
|
|
total += map[coord.y][coord.x] + 1; |
|
|
|
} |
|
|
|
|
|
|
|
return total; |
|
|
|
} |
|
|
|
|
|
|
|
unsigned recurse_basin(struct map2d input, unordered_set<unsigned> & basin, int y, int x) |
|
|
|
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); |
|
|
@ -85,24 +94,22 @@ unsigned recurse_basin(struct map2d input, unordered_set<unsigned> & basin, int |
|
|
|
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); |
|
|
|
if (cmp >= base) size += recurse_basin(input, basin, new_y, new_x); |
|
|
|
} |
|
|
|
return size; |
|
|
|
} |
|
|
|
|
|
|
|
unsigned part2(auto input) |
|
|
|
uint64_t part2(auto input, vector<coord2d> lowpoints) |
|
|
|
{ |
|
|
|
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); |
|
|
|
} |
|
|
|
for (coord2d coord : lowpoints) { |
|
|
|
unordered_set<unsigned> basin; |
|
|
|
biggest[0] = recurse_basin(input, basin, coord.y, coord.x); |
|
|
|
sort(biggest, biggest + 4); |
|
|
|
} |
|
|
|
|
|
|
|
return biggest[1] * biggest[2] * biggest[3]; |
|
|
|
return (uint64_t)biggest[1] * biggest[2] * biggest[3]; |
|
|
|
} |
|
|
|
|
|
|
|
int main(int argc, char *argv[]) |
|
|
@ -110,6 +117,7 @@ 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; |
|
|
|
vector<coord2d> lowpoints; |
|
|
|
cout << part1(input, lowpoints) << endl; |
|
|
|
cout << part2(input, lowpoints) << endl; |
|
|
|
} |
|
|
|