diff options
author | Adam Spragg <adam@spra.gg> | 2022-12-19 13:02:44 +0000 |
---|---|---|
committer | Adam Spragg <adam@spra.gg> | 2022-12-19 13:02:44 +0000 |
commit | 92db00a1c343680bf00123cc27153a4acef39a88 (patch) | |
tree | df65b68fe4d0c9d2641f0cd9ccb56b05a36934cf | |
parent | 5239ac78ba3a348bbabe49dc71bc7747ef232f28 (diff) |
Solve puzzle 18 part 1
-rw-r--r-- | 18.c | 154 | ||||
-rw-r--r-- | makefile | 1 |
2 files changed, 155 insertions, 0 deletions
@@ -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; +} + @@ -19,6 +19,7 @@ all: bin \ bin/15 \ bin/16 \ bin/17 \ + bin/18 \ bin: mkdir -p $@ |