2
1
Fork 0
aoc2021/20/solution.c
2021-12-20 13:24:50 +01:00

119 lines
2.8 KiB
C

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
static void pbm(char *front, size_t stride) {
printf("P1\n%lu %lu\n", stride, stride);
for (size_t i = 0; i < stride * stride; i++) {
putchar(front[i] ? '1' : '0');
}
}
int main(int argc, char **argv) {
int vis = 0, opt;
long long maxiter = 50;
while ((opt = getopt(argc, argv, "vi:")) != -1) {
switch (opt) {
case 'v':
vis = 1;
break;
case 'i':
maxiter = atoll(optarg);
break;
default:
usage:
fprintf(stderr, "Usage: %s [-v] [-i iterations] input\n\n"
"-v output is NetPBM, readable by FFmpeg\n",
argv[0]);
return 1;
}
}
if (optind >= argc)
goto usage;
char *algo = NULL, *front = NULL, *back = NULL, *s;
size_t stride = 0, S = 0, G = 0;
FILE *fp = fopen(argv[optind], "r");
if(!fp) {
fprintf(stderr, "%s: Could not open file '%s': ",
argv[0], argv[optind]);
perror("");
return 1;
}
fscanf(fp, "%ms", &algo);
while (fscanf(fp, "%ms\n", &s) == 1) {
size_t len = strlen(s);
char *dst;
if (!stride) {
stride = len * 3;
front = calloc(stride * stride, 1);
dst = front + stride * len;
}
dst += len;
for (size_t c = 0; c < len; c++)
*dst++ = s[c] == '#';
dst += len;
free(s);
}
fclose(fp);
back = malloc(stride * stride);
memcpy(back, front, stride * stride);
for (long long iter = 0; iter < maxiter; iter++) {
if (vis && iter & 1) pbm(front, stride);
if (iter == 2) {
for (int p = 0; p < stride * stride; p++)
S += front[p];
}
#pragma omp parallel for
for (size_t y = 0; y < stride; y++) {
for (size_t x = 0; x < stride; x++) {
int v = 0;
for (int yy = -1; yy <= 1; yy++) {
for (int xx = -1; xx <= 1; xx++) {
v <<= 1;
if (y + yy > 0 && y + yy < stride &&
x + xx > 0 && x + xx < stride)
v |= front[(y + yy) * stride + x + xx];
else
v |= iter & 1;
back[y * stride + x] = algo[v] == '#';
}
}
}
}
char *tmp=front;
front=back;
back=tmp;
}
for (size_t p = 0; p < stride * stride; p++)
G += front[p];
fprintf(stderr, "Silver: %lu\nGold: %lu\n", S, G);
free(front);
free(algo);
free(back);
}