--- /dev/null
+#include <stdio.h>
+
+#include <uthash.h>
+
+struct point {int x; int y; int gen; };
+struct entry {
+ struct point p;
+ char c;
+ UT_hash_handle hh;
+};
+
+char *key = NULL;
+
+void add_point(struct entry **board, int x, int y, int gen, char c)
+{
+ struct entry *e = calloc(1, sizeof(struct entry));
+ e->p = (struct point){.x=x, .y=y, .gen=gen};
+ e->c = c;
+ HASH_ADD(hh, *board, p, sizeof(struct point), e);
+}
+
+char get_point(struct entry **board, int x, int y, int gen)
+{
+ struct entry *e;
+ struct point p;
+ memset(&p, 0, sizeof(p));
+ p.x = x;
+ p.y = y;
+ p.gen = gen;
+ HASH_FIND(hh, *board, &p, sizeof(struct point), e);
+ if (e == NULL) {
+ if (key[0] == '#')
+ return gen % 2 == 0 ? '.' : '#';
+ else
+ return '.';
+ }
+ return e->c;
+}
+
+char evolve(struct entry **board, int px, int py, int gen)
+{
+ int r = 0;
+ for (int y = py-1; y<=py+1; y++)
+ for (int x = px-1; x<=px+1; x++)
+ r = r*2 + (get_point(board, x, y, gen) == '#' ? 1 : 0);
+ return key[r];
+}
+
+int main()
+{
+ size_t len = 0;
+ if (getline(&key, &len, stdin) == -1)
+ return -1;
+ if (getchar() != '\n')
+ return 1;
+
+ struct entry *board = NULL;
+ int x = 0, minx = 0, maxx = 0;
+ int y = 0, miny = 0, maxy = 0;
+
+ int c;
+ while ((c = getchar()) != EOF) {
+ if (c == '\n') {
+ if (x > maxx)
+ maxx = x;
+ x = 0;
+ y++;
+ } else {
+ add_point(&board, x++, y, 0, c);
+ }
+ }
+ maxy = y;
+
+ int gen = 1;
+ for (; gen <= 2; gen++) {
+ minx -= 3;
+ miny -= 3;
+ maxx += 3;
+ maxy += 3;
+
+ for (y = miny; y<maxy; y++)
+ for (x = minx; x<maxx; x++)
+ add_point(&board, x, y, gen,
+ evolve(&board, x, y, gen-1));
+ }
+
+ int r = 0;
+ for (y = miny; y<maxy; y++)
+ for (x = minx; x<maxx; x++)
+ if (get_point(&board, x, y, gen-1) == '#')
+ r++;
+ printf("%d\n", r);
+}