#include #include #include #include #include #define AT(x, y) grid[(y) * x_max + (x)] void get_limits(FILE *file, int *x_min, int *x_max, int *y_min, int *y_max) { char *line = NULL; size_t len; *x_min = INT_MAX; *x_max = INT_MAX; *x_max = 0; *y_max = 0; while (getline(&line, &len, file) != -1) { int xa, xb, ya, yb; if (sscanf(line, "x=%d, y=%d..%d", &xa, &ya, &yb) == 3) { if (xa < *x_min) *x_min = xa; if (xa + 1 > *x_max) *x_max = xa + 1; if (ya < *y_min) *y_min = ya; if (yb + 1 > *y_max) *y_max = yb + 1; } else if (sscanf(line, "y=%d, x=%d..%d", &ya, &xa, &xb) == 3) { if (xa < *x_min) *x_min = xa; if (xb + 1 > *x_max) *x_max = xa + 1; if (ya < *y_min) *y_min = ya; if (ya + 1 > *y_max) *y_max = yb + 1; } else { break; } } *x_max += 10; *x_min -= 10; printf("grid: x=%d..%d y=%d..%d\n", *x_min, *x_max, *y_min, *y_max); rewind(file); } void build_grid(FILE *file, char *grid, int x_max) { char *line = NULL; size_t len; while (getline(&line, &len, file) != -1) { int xa, xb, ya, yb; if (sscanf(line, "x=%d, y=%d..%d", &xa, &ya, &yb) == 3) { printf("x=%d, y=%d..%d\n", xa, ya, yb); for (int y = ya; y <= yb; y++) AT(xa, y) = '#'; } else if (sscanf(line, "y=%d, x=%d..%d", &ya, &xa, &xb) == 3) { printf("x=%d..%d, y=%d\n", xa, xb, ya); for (int x = xa; x <= xb; x++) AT(x, ya) = '#'; } else { break; } } grid[500] = '+'; } void print_grid(char *grid, int x_min, int x_max, int y_min, int y_max) { printf("\n"); printf(" "); for (int x = x_min; x < x_max; x++) printf("%d", x / 100 % 10); printf("\n"); printf(" "); for (int x = x_min; x < x_max; x++) printf("%d", x / 10 % 10); printf("\n"); printf(" "); for (int x = x_min; x < x_max; x++) printf("%d", x % 10); printf("\n"); for (int y = 0; y < y_max + 3; y++) { if (y < y_min || y >= y_max) printf("\033[41m"); printf("%4d \033[0m", y); for (int x = x_min; x < x_max; x++) { switch (grid[y * x_max + x]) { case '.': putchar(' '); putchar(' '); break; case '|': printf("\033[44m\u2551\u2551\033[0m"); break; case '~': printf("\033[44m\u2248\u2248\033[0m"); break; case '#': printf("\033[33m\u2588\u2588\033[0m"); break; case '+': printf("\033[41m\u256C\u256C\033[0m"); break; default: assert(0); } } putchar('\n'); } } char *read_grid(FILE *file, int *x_min, int *x_max, int *y_min, int *y_max) { get_limits(file, x_min, x_max, y_min, y_max); size_t size = (*y_max + 50) * *x_max; char *grid = malloc(size); memset(grid, '.', size); build_grid(file, grid, *x_max); return grid; } void step(char *grid, int x_min, int x_max, int y_min, int y_max) { for (int y = 0; y < y_max + 50; y++) { for (int x = x_min; x < x_max; x++) { if (AT(x, y) == '+' || AT(x, y) == '|') { if (AT(x, y + 1) == '.') { AT(x, y + 1) = '|'; } else if (AT(x, y + 1) == '#' || AT(x, y + 1) == '~') { int is_still = 1; int left_wall = -1, right_wall = -1; for (int x_ = x; x_ >= x_min - 1; x_--) { if (AT(x_, y) == '#') { left_wall = x_ + 1; break; } else if (AT(x_, y + 1) == '.' || AT(x_, y + 1) == '|') { is_still = 0; left_wall = x_; break; } } for (int x_ = x; x_ <= x_max; x_++) { if (AT(x_, y) == '#') { right_wall = x_ - 1; break; } else if (AT(x_, y + 1) == '.' || AT(x_, y + 1) == '|') { is_still = 0; right_wall = x_; break; } } if (left_wall != -1 && right_wall != -1) { for (int x_ = left_wall; x_ <= right_wall; x_++) { assert(AT(x_, y) != '#'); AT(x_, y) = is_still ? '~' : '|'; } } } } } } } int count_water(char *grid, int x_min, int x_max, int y_min, int y_max) { int water = 0; for (int y = y_min; y < y_max; y++) { for (int x = x_min; x < x_max; x++) { water += (AT(x, y) == '~') ? 1 : 0; } } return water; } int main(int argc, char **argv) { if (argc != 2) { printf("Usage: %s [input]\n", argv[0]); return EXIT_FAILURE; } FILE *file = fopen(argv[1], "r"); int x_min, x_max, y_min, y_max; char *grid = read_grid(file, &x_min, &x_max, &y_min, &y_max); print_grid(grid, x_min, x_max, y_min, y_max); int last_water = -1, water = -1; int extra_steps = 0; do { step(grid, x_min, x_max, y_min, y_max); last_water = water; water = count_water(grid, x_min, x_max, y_min, y_max); printf("Water: %d\r", water); if (last_water == water) extra_steps += 1; else extra_steps = 0; } while (extra_steps < 200); print_grid(grid, x_min, x_max, y_min, y_max); printf("Water: %d\n", water); }