Files
adventofcode2024/day11/c/day11.c

168 lines
4.0 KiB
C
Raw Normal View History

2024-12-13 14:25:51 +01:00
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_CHARS 1024
#define MAX_INITIAL_STONES 1024
#define MAX_LEAF_COUNT 16
typedef struct stone {
uint64_t value;
2024-12-13 18:13:20 +01:00
uint64_t multiplier;
struct stone *prev;
struct stone *next;
2024-12-13 14:25:51 +01:00
} stone_t;
2024-12-13 18:13:20 +01:00
void deallocate_ll(stone_t *leaf);
void iterate_ll(stone_t *, void (*cb)(stone_t*, void*), void* ctx);
2024-12-13 14:25:51 +01:00
2024-12-13 18:13:20 +01:00
void display(stone_t *stone, void* ctx) {
printf("%lu ", stone->value);
}
2024-12-13 14:25:51 +01:00
void blink(stone_t *leaf, void* ctx);
2024-12-13 18:13:20 +01:00
void count(stone_t *leaf, void* ctx);
void unlink(stone_t *stone);
2024-12-13 14:25:51 +01:00
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++;
}
2024-12-13 18:13:20 +01:00
stone_t *head;
2024-12-13 14:25:51 +01:00
2024-12-13 18:13:20 +01:00
for (int i = 0; i < stone_count; i++) {
2024-12-13 14:25:51 +01:00
stone_t *stone = calloc(1, sizeof(stone[0]));
2024-12-13 18:13:20 +01:00
stone->multiplier = 1;
stone->value = stones[i];
if (i == 0) {
head = stone;
continue;
2024-12-13 14:25:51 +01:00
}
2024-12-13 18:13:20 +01:00
stone_t *tmp = head;
while(tmp->next != NULL) tmp = tmp->next;
tmp->next = stone;
stone->prev = tmp;
2024-12-13 14:25:51 +01:00
}
free(stones);
2024-12-13 18:13:20 +01:00
free(buf);
2024-12-13 14:25:51 +01:00
2024-12-13 18:13:20 +01:00
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);
}
2024-12-13 14:25:51 +01:00
}
2024-12-13 18:13:20 +01:00
cnt = 0;
iterate_ll(head, count, &cnt);
2024-12-13 16:04:05 +01:00
2024-12-13 18:13:20 +01:00
printf("%lu\n", cnt);
2024-12-13 14:25:51 +01:00
2024-12-13 18:13:20 +01:00
deallocate_ll(head);
}
2024-12-13 15:56:59 +01:00
2024-12-13 18:13:20 +01:00
void deallocate_ll(stone_t *leaf) {
if (leaf == NULL) {
return;
2024-12-13 14:25:51 +01:00
}
2024-12-13 18:13:20 +01:00
stone_t* next = leaf->next;
2024-12-13 15:56:59 +01:00
free(leaf);
2024-12-13 18:13:20 +01:00
deallocate_ll(next);
}
void iterate_ll(stone_t *leaf, void (*cb)(stone_t*, void*), void* ctx) {
if (leaf == NULL) {
return;
}
2024-12-13 15:56:59 +01:00
2024-12-13 18:13:20 +01:00
cb(leaf, ctx);
iterate_ll(leaf->next, cb, ctx);
2024-12-13 14:25:51 +01:00
}
void blink(stone_t *leaf, void* ctx) {
if (leaf->value == 0) {
2024-12-13 18:13:20 +01:00
leaf->value = 1;
2024-12-13 14:25:51 +01:00
} 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]));
2024-12-13 18:13:20 +01:00
left_stone->multiplier = leaf->multiplier;
2024-12-13 14:25:51 +01:00
sscanf(left, "%lu", &left_stone->value);
2024-12-13 18:13:20 +01:00
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;
2024-12-13 14:25:51 +01:00
} else {
2024-12-13 18:13:20 +01:00
leaf->value *= 2024;
2024-12-13 14:25:51 +01:00
}
}
}
2024-12-13 18:13:20 +01:00
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;
}
}