--- /dev/null
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdbool.h>
+#include <limits.h>
+#include <uthash.h>
+
+struct point { int x; int y; };
+struct entry { struct point key; UT_hash_handle hh; };
+
+#define push(x, y) {\
+ if ((x) >= 1 && (y) >= 1 && (x) <= maxx+1 && (y) <= maxy+1)\
+ stack[sp++] = (struct point){x, y};\
+ }
+
+int basin(int grid[102][102], int maxx, int maxy, int x, int y)
+{
+ printf("calculate basin for: %d,%d -- ", x, y);
+ struct point stack[1000];
+ memset(stack, 0, sizeof stack);
+ struct entry *visited = NULL;
+
+ int sp = 0;
+ int size = 0;
+ stack[sp++] = (struct point){.x=x, .y=y};
+
+ struct point p;
+ struct entry *e;
+ memset(&p, 0, sizeof p);
+ while(--sp >= 0) {
+ p = stack[sp];
+ HASH_FIND(hh, visited, &p, sizeof(struct point), e);
+ if (e)
+ continue;
+
+ e = calloc(1, sizeof(struct entry));
+ e->key = p;
+ HASH_ADD(hh, visited, key, sizeof(struct point), e);
+
+ if (grid[p.y][p.x] == 9)
+ continue;
+ size++;
+
+ push(p.x+1, p.y);
+ push(p.x-1, p.y);
+ push(p.x, p.y+1);
+ push(p.x, p.y-1);
+ }
+ printf(" %d\n", size);
+ return size;
+}
+
+void insert(int tl[3], int s)
+{
+ if (s > tl[0] && s <= tl[1])
+ tl[0] = s;
+ if (s > tl[1] && s <= tl[2]) {
+ tl[0] = tl[1];
+ tl[1] = s;
+ }
+ if (s > tl[2]) {
+ tl[0] = tl[1];
+ tl[1] = tl[2];
+ tl[2] = s;
+ }
+}
+
+int main()
+{
+ int grid[102][102];
+ for (int i = 0; i<102; i++)
+ for (int j = 0; j<102; j++)
+ grid[i][j] = 9;
+ int x = 1, y = 1;
+ int maxx = 1;
+ int c = 0;
+ while((c = getchar()) != EOF) {
+ if (c == '\n') {
+ y++;
+ x = 1;
+ } else {
+ maxx = x > maxx ? x : maxx;
+ grid[y][x++] = c-'0';
+ }
+ }
+
+ int tl[3] = {0};
+ for (int cy = 1; cy<y; cy++)
+ for (int cx = 1; cx<maxx+1; cx++)
+ if (grid[cy][cx] < grid[cy+1][cx] &&
+ grid[cy][cx] < grid[cy-1][cx] &&
+ grid[cy][cx] < grid[cy][cx+1] &&
+ grid[cy][cx] < grid[cy][cx-1])
+ insert(tl, basin(grid, maxx, y, cx, cy));
+ printf("%d %d %d\n", tl[0], tl[1], tl[2]);
+ printf("%d\n", tl[0]*tl[1]*tl[2]);
+}