Add day 17
This commit is contained in:
parent
007234f7b2
commit
b45596b6a8
1 changed files with 197 additions and 0 deletions
197
Day17/Day17A.c
Normal file
197
Day17/Day17A.c
Normal file
|
@ -0,0 +1,197 @@
|
|||
#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);
|
||||
}
|
Loading…
Reference in a new issue