Files
adventofcode2024/day11/c/day11.c
dobiadi b6e8549f24 Less
2024-12-13 16:04:05 +01:00

123 lines
2.9 KiB
C

#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <omp.h>
#define MAX_CHARS 1024
#define MAX_INITIAL_STONES 1024
#define MAX_LEAF_COUNT 16
typedef struct stone {
uint64_t value;
struct stone *leafs[2];
int leaf_count;
} stone_t;
void add_leaf(stone_t* root, stone_t* leaf);
uint64_t call_on_leaf(stone_t *leaf, void (*cb)(stone_t*, void*), void* ctx);
void blink(stone_t *leaf, void* ctx);
int main() {
char c, *p, *buf;
buf = calloc(MAX_CHARS, sizeof(buf[0]));
p = buf;
while ((c = getchar()) != EOF) {
*p++ = c;
}
size_t in = p - buf;
int stone_count = 0;
uint64_t *stones = calloc(MAX_INITIAL_STONES, sizeof(stones[0]));
for (size_t i = 0; i < in;) {
p = buf + i;
sscanf(p, "%lu", &stones[stone_count++]);
do {
i++;
} while(i < in && *(buf+i) != ' ');
i++;
}
free(buf);
//call_on_leaf(root, display, NULL);
//printf("\n");
uint64_t sum = 0;
#pragma omp parallel for
for (int j = 0; j < stone_count; j++) {
int blink_count = 75;
stone_t *stone = calloc(1, sizeof(stone[0]));
stone->value = stones[j];
uint64_t s = call_on_leaf(stone, blink, &blink_count);
#pragma omp critical
{
sum += s;
}
}
free(stones);
printf("%lu\n", sum);
}
void add_leaf(stone_t* root, stone_t* leaf) {
root->leafs[root->leaf_count++] = leaf;
}
uint64_t call_on_leaf(stone_t *leaf, void (*cb)(stone_t*, void*), void* ctx) {
if (*(int*)ctx == 0) {
free(leaf);
return 1;
}
cb(leaf, ctx);
uint64_t sum = 0;
(*(int*)ctx)--;
for (int i = 0; i < leaf->leaf_count; i++) {
sum += call_on_leaf(leaf->leafs[i], cb, ctx);
}
(*(int*)ctx)++;
free(leaf);
return sum;
}
void blink(stone_t *leaf, void* ctx) {
if (leaf->value == 0) {
stone_t *next = calloc(1, sizeof(next[0]));
next->value = 1;
add_leaf(leaf, next);
} else {
// Split in two
char buf[64];
sprintf(buf, "%lu", leaf->value);
size_t len = strlen(buf);
if (len % 2 == 0) {
char left[32];
memcpy(left, buf, len / 2);
left[len / 2] = '\0';
char right[32];
memcpy(right, buf + len / 2, len / 2);
right[len / 2] = '\0';
stone_t *left_stone = calloc(1, sizeof(left_stone[0]));
stone_t *right_stone = calloc(1, sizeof(right_stone[0]));
sscanf(left, "%lu", &left_stone->value);
sscanf(right, "%lu", &right_stone->value);
add_leaf(leaf, left_stone);
add_leaf(leaf, right_stone);
} else {
stone_t *next = calloc(1, sizeof(next[0]));
next->value = leaf->value * 2024;
add_leaf(leaf, next);
}
}
}