198 lines
5.9 KiB
C
198 lines
5.9 KiB
C
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <limits.h>
|
|
#include <assert.h>
|
|
#include <string.h>
|
|
|
|
#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);
|
|
}
|