//#define _GNU_SOURCE #include #include #include #include #define arrlen(x) (sizeof(x)/sizeof((x)[0])) struct point { int x; int y; int z; }; int point_cmp(struct point const * a, struct point 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 point_cmp_t(void const * a, void const * b) { return point_cmp(a, b); } // Get one of the faces of a cube // // x = left-right // y = up-down // z = front-back // // To uniquely identify the faces of a cube, we scale the cube by a factor of // two, and then identify each face by the point at the face's center. struct point * cube_face(int x, int y, int z, int face) { struct point * 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 point))) == 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 point * face = cube_face(x, y, z, f); struct point * exists = *((struct point **) tsearch(face, &faces, point_cmp_t)); if (exists == face) { // Inserted new face ++nfaces; } else { // Face already existed, so delete it tdelete(face, &faces, point_cmp_t); --nfaces; free(face); free(exists); } } } printf("Faces: %d\n", nfaces); #ifdef _GNU_SOURCE tdestroy(faces, free); #endif regfree(&cube); return 0; }