141 lines
4.3 KiB
C
141 lines
4.3 KiB
C
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <omp.h>
|
|
|
|
#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;
|
|
}
|