diff --git a/Day17/Day17A.c b/Day17/Day17A.c new file mode 100644 index 0000000..28182ab --- /dev/null +++ b/Day17/Day17A.c @@ -0,0 +1,197 @@ +#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); +}