summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--18.c154
-rw-r--r--makefile1
2 files changed, 155 insertions, 0 deletions
diff --git a/18.c b/18.c
new file mode 100644
index 0000000..05c7940
--- /dev/null
+++ b/18.c
@@ -0,0 +1,154 @@
+
+//#define _GNU_SOURCE
+
+#include <regex.h>
+#include <search.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+
+#define arrlen(x) (sizeof(x)/sizeof((x)[0]))
+
+
+struct face {
+ int x;
+ int y;
+ int z;
+};
+
+
+int
+face_cmp(struct face const * a, struct face const * b)
+{
+ if (a->x != b->x)
+ return a->x - b->x;
+ if (a->y != b->y)
+ return a->y - b->y;
+ return a->z - b->z;
+}
+
+
+int
+face_cmp_t(void const * a, void const * b)
+{
+ return face_cmp(a, b);
+}
+
+
+// Get one of the faces of a cube
+//
+// x = left-right
+// y = up-down
+// z = front-back
+//
+// For a cube, we scale it by a factor of two, and then identify each face by
+// the point at its center.
+struct face *
+cube_face(int x, int y, int z, int face)
+{
+ struct face * f;
+
+ x *= 2;
+ y *= 2;
+ z *= 2;
+
+ switch (face) {
+ case 0: // Bottom face
+ x += 1;
+ z += 1;
+ break;
+
+ case 1: // Top face
+ x += 1;
+ y += 2;
+ z += 1;
+ break;
+
+ case 2: // Left face
+ y += 1;
+ z += 1;
+ break;
+
+ case 3: // Right face
+ x += 2;
+ y += 1;
+ z += 1;
+ break;
+
+ case 4: // Front face
+ x += 1;
+ y += 1;
+ break;
+
+ case 5: // Back face
+ x += 1;
+ y += 1;
+ z += 2;
+ break;
+
+ default:
+ return NULL;
+ }
+
+ if ((f = malloc(sizeof(struct face))) == NULL)
+ return NULL;
+
+ f->x = x;
+ f->y = y;
+ f->z = z;
+ return f;
+}
+
+
+int
+main()
+{
+ char buf[BUFSIZ];
+ regex_t cube;
+ regmatch_t coords[4];
+ void * faces = NULL;
+ int nfaces = 0;
+
+ if (regcomp(&cube, "(-?[[:digit:]]+),(-?[[:digit:]]+),(-?[[:digit:]]+)", REG_EXTENDED) != 0) {
+ fprintf(stderr, "Bad regex\n");
+ return -1;
+ }
+
+ while (fgets(buf, sizeof(buf), stdin)
+ && regexec(&cube, buf, arrlen(coords), coords, 0) == 0)
+ {
+ int x, y, z, f;
+
+ x = atoi(buf + coords[1].rm_so);
+ y = atoi(buf + coords[2].rm_so);
+ z = atoi(buf + coords[3].rm_so);
+
+ for (f = 0; f < 6; ++f) {
+ struct face * face = cube_face(x, y, z, f);
+
+ struct face * exists = *((struct face **) tsearch(face, &faces, face_cmp_t));
+
+ if (exists == face) {
+ // Inserted new face
+ ++nfaces;
+ }
+ else {
+ // Face already existed, so delete it
+ tdelete(face, &faces, face_cmp_t);
+ --nfaces;
+ free(face);
+ free(exists);
+ }
+ }
+ }
+
+ printf("Faces: %d\n", nfaces);
+
+#ifdef _GNU_SOURCE
+ tdestroy(faces, free);
+#endif
+ regfree(&cube);
+
+ return 0;
+}
+
diff --git a/makefile b/makefile
index b4f98af..2a45609 100644
--- a/makefile
+++ b/makefile
@@ -19,6 +19,7 @@ all: bin \
bin/15 \
bin/16 \
bin/17 \
+ bin/18 \
bin:
mkdir -p $@