#include #include #include #include #define MAX_CHARS 1024 #define MAX_INITIAL_STONES 1024 #define MAX_LEAF_COUNT 16 typedef struct stone { uint64_t value; uint64_t multiplier; struct stone *prev; struct stone *next; } stone_t; void deallocate_ll(stone_t *leaf); 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 count(stone_t *leaf, void* ctx); void unlink(stone_t *stone); 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++; } stone_t *head; for (int i = 0; i < stone_count; i++) { stone_t *stone = calloc(1, sizeof(stone[0])); stone->multiplier = 1; stone->value = stones[i]; if (i == 0) { head = stone; continue; } stone_t *tmp = head; while(tmp->next != NULL) tmp = tmp->next; tmp->next = stone; stone->prev = tmp; } free(stones); free(buf); 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 deallocate_ll(stone_t *leaf) { if (leaf == NULL) { return; } stone_t* next = leaf->next; free(leaf); deallocate_ll(next); } void iterate_ll(stone_t *leaf, void (*cb)(stone_t*, void*), void* ctx) { if (leaf == NULL) { return; } cb(leaf, ctx); iterate_ll(leaf->next, cb, ctx); } void blink(stone_t *leaf, void* ctx) { if (leaf->value == 0) { leaf->value = 1; } 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])); left_stone->multiplier = leaf->multiplier; sscanf(left, "%lu", &left_stone->value); sscanf(right, "%lu", &leaf->value); if (leaf->prev) { left_stone->prev = leaf->prev; leaf->prev->next = left_stone; } leaf->prev = left_stone; left_stone->next = leaf; } else { leaf->value *= 2024; } } } 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; } }