Files
adventofcode2023/day22/c/day22.c

141 lines
4.3 KiB
C
Raw Normal View History

2023-12-23 21:12:34 +01:00
#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;
}