Final Day11

This commit is contained in:
dobiadi
2024-12-13 18:13:20 +01:00
parent b6e8549f24
commit 229eaa2fee
2 changed files with 93 additions and 48 deletions

View File

Binary file not shown.

View File

@@ -2,7 +2,6 @@
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <omp.h>
#define MAX_CHARS 1024 #define MAX_CHARS 1024
#define MAX_INITIAL_STONES 1024 #define MAX_INITIAL_STONES 1024
@@ -10,14 +9,20 @@
typedef struct stone { typedef struct stone {
uint64_t value; uint64_t value;
struct stone *leafs[2]; uint64_t multiplier;
int leaf_count; struct stone *prev;
struct stone *next;
} stone_t; } stone_t;
void add_leaf(stone_t* root, stone_t* leaf); void deallocate_ll(stone_t *leaf);
uint64_t call_on_leaf(stone_t *leaf, void (*cb)(stone_t*, void*), void* ctx); void iterate_ll(stone_t *, void (*cb)(stone_t*, void*), void* ctx);
void display(stone_t *stone, void* ctx) {
printf("%lu ", stone->value);
}
void blink(stone_t *leaf, void* ctx); void blink(stone_t *leaf, void* ctx);
void count(stone_t *leaf, void* ctx);
void unlink(stone_t *stone);
int main() { int main() {
char c, *p, *buf; char c, *p, *buf;
@@ -43,58 +48,82 @@ int main() {
i++; i++;
} }
free(buf); stone_t *head;
//call_on_leaf(root, display, NULL); for (int i = 0; i < stone_count; i++) {
//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_t *stone = calloc(1, sizeof(stone[0]));
stone->value = stones[j]; stone->multiplier = 1;
uint64_t s = call_on_leaf(stone, blink, &blink_count); stone->value = stones[i];
#pragma omp critical if (i == 0) {
{ head = stone;
sum += s; continue;
} }
stone_t *tmp = head;
while(tmp->next != NULL) tmp = tmp->next;
tmp->next = stone;
stone->prev = tmp;
} }
free(stones); free(stones);
free(buf);
printf("%lu\n", sum); int blink_count = 75;
uint64_t cnt = 0;
for (int i = 0; i < blink_count; i++) {
iterate_ll(head, blink, NULL);
while(head->prev != NULL) head = head->prev;
// Deduplicate
stone_t *tmp = head;
while (tmp != NULL) {
uint64_t value = tmp->value;
stone_t *tmp2 = tmp->next;
while (tmp2 != NULL) {
if (tmp2->value == tmp->value) {
tmp->multiplier += tmp2->multiplier;
stone_t *tmp3 = tmp2;
tmp2 = tmp2->next;
unlink(tmp3);
free(tmp3);
continue;
}
tmp2 = tmp2->next;
}
tmp = tmp->next;
}
if (i == 24) {
iterate_ll(head, count, &cnt);
printf("%lu\n", cnt);
}
}
cnt = 0;
iterate_ll(head, count, &cnt);
printf("%lu\n", cnt);
deallocate_ll(head);
} }
void add_leaf(stone_t* root, stone_t* leaf) { void deallocate_ll(stone_t *leaf) {
root->leafs[root->leaf_count++] = leaf; if (leaf == NULL) {
return;
} }
stone_t* next = leaf->next;
uint64_t call_on_leaf(stone_t *leaf, void (*cb)(stone_t*, void*), void* ctx) {
if (*(int*)ctx == 0) {
free(leaf); free(leaf);
return 1; deallocate_ll(next);
} }
void iterate_ll(stone_t *leaf, void (*cb)(stone_t*, void*), void* ctx) {
if (leaf == NULL) {
return;
}
cb(leaf, ctx); cb(leaf, ctx);
iterate_ll(leaf->next, cb, 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) { void blink(stone_t *leaf, void* ctx) {
if (leaf->value == 0) { if (leaf->value == 0) {
stone_t *next = calloc(1, sizeof(next[0])); leaf->value = 1;
next->value = 1;
add_leaf(leaf, next);
} else { } else {
// Split in two // Split in two
char buf[64]; char buf[64];
@@ -108,15 +137,31 @@ void blink(stone_t *leaf, void* ctx) {
memcpy(right, buf + len / 2, len / 2); memcpy(right, buf + len / 2, len / 2);
right[len / 2] = '\0'; right[len / 2] = '\0';
stone_t *left_stone = calloc(1, sizeof(left_stone[0])); stone_t *left_stone = calloc(1, sizeof(left_stone[0]));
stone_t *right_stone = calloc(1, sizeof(right_stone[0])); left_stone->multiplier = leaf->multiplier;
sscanf(left, "%lu", &left_stone->value); sscanf(left, "%lu", &left_stone->value);
sscanf(right, "%lu", &right_stone->value); sscanf(right, "%lu", &leaf->value);
add_leaf(leaf, left_stone); if (leaf->prev) {
add_leaf(leaf, right_stone); left_stone->prev = leaf->prev;
leaf->prev->next = left_stone;
}
leaf->prev = left_stone;
left_stone->next = leaf;
} else { } else {
stone_t *next = calloc(1, sizeof(next[0])); leaf->value *= 2024;
next->value = leaf->value * 2024;
add_leaf(leaf, next);
} }
} }
} }
void count(stone_t *leaf, void* ctx) {
(*(uint64_t*)ctx) += leaf->multiplier;
}
void unlink(stone_t *stone) {
if (stone->prev) {
stone->prev->next = stone->next;
}
if (stone->next) {
stone->next->prev = stone->prev;
}
}