#include #include #include #include #define LINE_MAX_LENGTH 256 #define MAX_BRICKS 2048 #define NUM_0_CHARCODE 48 #define NUM_9_CHARCODE NUM_0_CHARCODE + 9 #define max(a,b) ((a) > (b) ? (a) : (b)) #define min(a,b) ((a) < (b) ? (a) : (b)) #define in_range(c,a,b) ((c) <= max(a,b) && (c) >= min(a,b)) typedef struct corner { int x; int y; int z; } corner_t; typedef struct brick { corner_t corners[2]; int fallen; } brick_t; int fall(brick_t bricks[], int bricks_num); int intersect(brick_t brick_a, brick_t brick_b); int main() { char *p, *buf, c; buf = (char *)malloc(LINE_MAX_LENGTH); memset(buf, 0, LINE_MAX_LENGTH); p = buf; brick_t bricks[MAX_BRICKS]; int bricks_num = 0; while ((c = getchar()) != EOF) { *p++ = c; if (c == '\n') { p = buf; sscanf(p, "%i", &bricks[bricks_num].corners[0].x); while (*p != ',') p++; p++; sscanf(p, "%i", &bricks[bricks_num].corners[0].y); while (*p != ',') p++; p++; sscanf(p, "%i", &bricks[bricks_num].corners[0].z); while (*p != '~') p++; p++; sscanf(p, "%i", &bricks[bricks_num].corners[1].x); while (*p != ',') p++; p++; sscanf(p, "%i", &bricks[bricks_num].corners[1].y); while (*p != ',') p++; p++; sscanf(p, "%i", &bricks[bricks_num].corners[1].z); bricks_num++; memset(buf, 0, LINE_MAX_LENGTH); p = buf; } } while (fall(bricks, bricks_num)); for (int i = 0; i < bricks_num; i++) { bricks[i].fallen = 0; } int part1 = 0; int part2 = 0; #pragma omp parallel for schedule(dynamic) for (int i = 0; i < bricks_num; i++) { brick_t bricks_copy[MAX_BRICKS]; memcpy(bricks_copy, bricks, sizeof(bricks)); bricks_copy[i].corners[0].z = 0; bricks_copy[i].corners[1].z = 0; int fallen = 0; while (fall(bricks_copy, bricks_num)); for (int j = 0; j < bricks_num; j++) { fallen += bricks_copy[j].fallen; } #pragma omp critical { if (fallen == 0) { part1++; } part2 += fallen; } } printf("%i\n", part1); printf("%i\n", part2); free(buf); } int fall(brick_t bricks[], int bricks_num) { int result = 0; for (int i = 0; i < bricks_num; i++) { int fallen = 0; for (;;) { bricks[i].corners[0].z--; bricks[i].corners[1].z--; if (bricks[i].corners[0].z <= 0 || bricks[i].corners[1].z <= 0) { break; } int collision = 0; for (int j = 0; j < bricks_num; j++) { if (i == j) continue; if (intersect(bricks[i], bricks[j])) { collision = 1; break; } } if (collision) { break; } bricks[i].fallen = 1; fallen = 1; } bricks[i].corners[0].z++; bricks[i].corners[1].z++; result += fallen; } return result; } int intersect(brick_t brick_a, brick_t brick_b) { if ( (in_range(brick_b.corners[0].x, brick_a.corners[0].x, brick_a.corners[1].x) || in_range(brick_b.corners[1].x, brick_a.corners[0].x, brick_a.corners[1].x) || in_range(brick_a.corners[1].x, brick_b.corners[0].x, brick_b.corners[1].x) || in_range(brick_a.corners[0].x, brick_b.corners[0].x, brick_b.corners[1].x)) && (in_range(brick_b.corners[0].y, brick_a.corners[0].y, brick_a.corners[1].y) || in_range(brick_b.corners[1].y, brick_a.corners[0].y, brick_a.corners[1].y) || in_range(brick_a.corners[1].y, brick_b.corners[0].y, brick_b.corners[1].y) || in_range(brick_a.corners[0].y, brick_b.corners[0].y, brick_b.corners[1].y)) && (in_range(brick_b.corners[0].z, brick_a.corners[0].z, brick_a.corners[1].z) || in_range(brick_b.corners[1].z, brick_a.corners[0].z, brick_a.corners[1].z) || in_range(brick_a.corners[1].z, brick_b.corners[0].z, brick_b.corners[1].z) || in_range(brick_a.corners[0].z, brick_b.corners[0].z, brick_b.corners[1].z)) ) { return 1; } return 0; }