commit 7d62a62fd4da5f2b8ddb03efe5b99fba5e3709bb
parent 69fdaf5b54c33f5597f235aa3f71ee5b810e7eae
Author: Sebastiano Tronto <sebastiano@tronto.net>
Date: Fri, 22 Dec 2023 16:44:48 +0100
Added solutions for 21 and 22
Diffstat:
6 files changed, 299 insertions(+), 0 deletions(-)
diff --git a/2023/21/21a.c b/2023/21/21a.c
@@ -0,0 +1,54 @@
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#define N 200
+
+typedef struct { int i, j; } point_t;
+
+char map[N][N];
+int n, nq, nnext;
+point_t s, q[N*N], nextq[N*N];
+
+bool bad(point_t p) {
+ int i = p.i, j = p.j;
+ return i < 0 || j < 0 || i >= n || j >= n || map[i][j] == '#';
+}
+
+void add(point_t p) {
+ if (bad(p)) return;
+ for (int i = 0; i < nnext; i++)
+ if (nextq[i].i == p.i && nextq[i].j == p.j)
+ return;
+ nextq[nnext++] = p;
+}
+
+point_t up(point_t p) { return (point_t) {.i = p.i-1, .j = p.j}; }
+point_t down(point_t p) { return (point_t) {.i = p.i+1, .j = p.j}; }
+point_t right(point_t p) { return (point_t) {.i = p.i, .j = p.j+1}; }
+point_t left(point_t p) { return (point_t) {.i = p.i, .j = p.j-1}; }
+
+int main() {
+ for (n = 0; fgets(map[n], N, stdin) != NULL; n++)
+ for (int i = 0; map[n][i] != '\n'; i++)
+ if (map[n][i] == 'S')
+ s = (point_t) {.i = n, .j = i};
+
+ int d = 64;
+ add(s);
+ for (int i = 0; i < d; i++) {
+ memcpy(q, nextq, nnext * sizeof(point_t));
+ nq = nnext;
+ nnext = 0;
+ for (int j = 0; j < nq; j++) {
+ add(up(q[j]));
+ add(down(q[j]));
+ add(right(q[j]));
+ add(left(q[j]));
+ }
+ }
+
+ printf("%d\n", nnext);
+ return 0;
+}
diff --git a/2023/21/21b.c b/2023/21/21b.c
@@ -0,0 +1,83 @@
+/*
+This is another problem I did not enjoy. Once again, it was only solvable
+because of the carefully crafted input case. This makes the problem
+solvable, but at the same time it leaves you wondering - which unsaid
+assumptions are true and which are not?
+
+For example, in my first 14 attempts or so I assumed that every non-# cell
+was reached at the same time as if there were no #-cells. A reasonable
+assumption, and almost true. Unfortunately there were some cells that
+were completely enclosed by #-cells, and thus unreachable. See fuckyou.png
+and fuckyou2.png.
+*/
+
+#include <inttypes.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#define N 200
+#define S 202300L /* My input was 202300*131+65 */
+
+char map[N][N];
+int64_t n;
+
+int go(char m[][N], int i, int j) {
+ if (i >= 0 && j >= 0 && i < n && j < n && m[i][j] == '.') {
+ m[i][j] = 'S';
+ return 1;
+ }
+ return 0;
+}
+
+int64_t flood(int64_t x, int64_t y, int64_t steps) {
+ int64_t c, i, j;
+ char tmp[N][N];
+ for (int i = 0; i < n; i++) memcpy(tmp[i], map[i], n*sizeof(char));
+ tmp[x][y] = 'S';
+ for (int s = 0; s < steps; s++) {
+ for (i = 0, c = 0; i < n; i++) {
+ for (j = (s+x+y+i)%2; j < n; j += 2) {
+ if (tmp[i][j] == 'S') {
+ tmp[i][j] = '.';
+ c += go(tmp, i-1, j) +
+ go(tmp, i+1, j) +
+ go(tmp, i, j-1) +
+ go(tmp, i, j+1);
+ }
+ }
+ }
+ }
+ return c;
+}
+
+int main() {
+ for (n = 0; fgets(map[n], N, stdin) != NULL; n++) ;
+ map[n/2][n/2] = '.';
+
+ int64_t fulleven = flood(n/2, n/2, n-1);
+ int64_t fullodd = flood(n/2, n/2, n);
+ int64_t arrowr = flood(n/2, 0, n-1);
+ int64_t arrowl = flood(n/2, n-1, n-1);
+ int64_t arrowd = flood(0, n/2, n-1);
+ int64_t arrowu = flood(n-1, n/2, n-1);
+ int64_t topl = flood(0, 0, n/2-1);
+ int64_t topr = flood(0, n-1, n/2-1);
+ int64_t botl = flood(n-1, 0, n/2-1);
+ int64_t botr = flood(n-1, n-1, n/2-1);
+ int64_t cutbr = flood(0, 0, n/2+n-1);
+ int64_t cutbl = flood(0, n-1, n/2+n-1);
+ int64_t cuttr = flood(n-1, 0, n/2+n-1);
+ int64_t cuttl = flood(n-1, n-1, n/2+n-1);
+
+ int64_t fulls = S*S*fulleven + (S-1)*(S-1)*fullodd;
+ int64_t smallborder = S*(topl + topr + botl + botr);
+ int64_t bigborder = (S-1)*(cutbr + cutbl + cuttr + cuttl);
+ int64_t arrows = arrowr + arrowl + arrowu + arrowd;
+ int64_t final = fulls + smallborder + bigborder + arrows;
+
+ printf("%" PRId64 "\n", final);
+
+ return 0;
+}
diff --git a/2023/21/fuckyou.png b/2023/21/fuckyou.png
Binary files differ.
diff --git a/2023/21/fuckyou2.png b/2023/21/fuckyou2.png
Binary files differ.
diff --git a/2023/22/22a.c b/2023/22/22a.c
@@ -0,0 +1,77 @@
+#include <inttypes.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#define N 1500
+#define M 340
+#define MAX(x,y) ((x)>(y)?(x):(y))
+
+#define isnum(c) (c == '-' || (c >= '0' && c <= '9'))
+
+char line[N];
+int n, x, b[N][6], cube[M][M][M];
+
+void readl(int nums[], char *buf) {
+ for (int i = 0; i < 6; i++) {
+ nums[i] = atoi(buf);
+ while (isnum(*buf)) buf++;
+ buf++;
+ }
+}
+
+bool droppable(int i) {
+ int z = b[i][2];
+ if (z == 1) return false;
+ for (int x = b[i][0]; x <= b[i][3]; x++)
+ for (int y = b[i][1]; y <= b[i][4]; y++)
+ if (cube[x][y][z-1])
+ return false;
+ return true;
+}
+
+void set(int n, int c) {
+ for (int i = b[n][0]; i <= b[n][3]; i++)
+ for (int j = b[n][1]; j <= b[n][4]; j++)
+ for (int k = b[n][2]; k <= b[n][5]; k++)
+ cube[i][j][k] = c;
+}
+
+void dobreak(int n) { set(n, 0); }
+void unbreak(int n) { set(n, n+1); }
+
+void drop(int i) {
+ dobreak(i);
+ b[i][2]--;
+ b[i][5]--;
+ unbreak(i);
+}
+
+int disintegratable(int i) {
+ int ret = 1;
+ dobreak(i);
+ for (int j = 0; j < n; j++)
+ if (j != i && droppable(j))
+ ret = 0;
+ unbreak(i);
+ return ret;
+}
+
+int main() {
+ for (n = 0; fgets(line, N, stdin) != NULL; n++) {
+ readl(b[n], line);
+ unbreak(n);
+ }
+
+ for (int i = 0; i < N; i++)
+ for (int j = 0; j < n; j++)
+ while (droppable(j))
+ drop(j);
+
+ for (int i = 0; i < n; i++)
+ x += disintegratable(i);
+
+ printf("%d\n", x);
+ return 0;
+}
diff --git a/2023/22/22b.c b/2023/22/22b.c
@@ -0,0 +1,85 @@
+#include <inttypes.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#define N 1500
+#define M 340
+#define MAX(x,y) ((x)>(y)?(x):(y))
+
+#define isnum(c) (c == '-' || (c >= '0' && c <= '9'))
+
+char line[N];
+int n, x, b[N][6], cube[M][M][M];
+
+void readl(int nums[], char *buf) {
+ for (int i = 0; i < 6; i++) {
+ nums[i] = atoi(buf);
+ while (isnum(*buf)) buf++;
+ buf++;
+ }
+}
+
+bool droppable(int i) {
+ int z = b[i][2];
+ if (z == 1) return false;
+ if (!cube[b[i][0]][b[i][1]][b[i][2]]) return false; /* Already dropping */
+ for (int x = b[i][0]; x <= b[i][3]; x++)
+ for (int y = b[i][1]; y <= b[i][4]; y++)
+ if (cube[x][y][z-1])
+ return false;
+ return true;
+}
+
+void set(int n, int c) {
+ for (int i = b[n][0]; i <= b[n][3]; i++)
+ for (int j = b[n][1]; j <= b[n][4]; j++)
+ for (int k = b[n][2]; k <= b[n][5]; k++)
+ cube[i][j][k] = c;
+}
+
+void dobreak(int n) { set(n, 0); }
+void unbreak(int n) { set(n, n+1); }
+
+void drop(int i) {
+ dobreak(i);
+ b[i][2]--;
+ b[i][5]--;
+ unbreak(i);
+}
+
+int howmanyfall(int i) {
+ int k = 0, q[N];
+ q[k++] = i;
+ dobreak(i);
+ for (int t = 0; t < k; t++) {
+ for (int j = 0; j < n; j++) {
+ if (j != q[t] && droppable(j)) {
+ q[k++] = j;
+ dobreak(j);
+ }
+ }
+ }
+ for (int s = 0; s < k; s++)
+ unbreak(q[s]);
+ return k-1;
+}
+
+int main() {
+ for (n = 0; fgets(line, N, stdin) != NULL; n++) {
+ readl(b[n], line);
+ unbreak(n);
+ }
+
+ for (int i = 0; i < N; i++)
+ for (int j = 0; j < n; j++)
+ while (droppable(j))
+ drop(j);
+
+ for (int i = 0; i < n; i++)
+ x += homanyfall(i);
+
+ printf("%d\n", x);
+ return 0;
+}