132 lines
3.0 KiB
C
132 lines
3.0 KiB
C
#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;
|
|
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);
|
|
|
|
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->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;
|
|
for (int i = 0; i < blink_count; i++) {
|
|
iterate_ll(head, blink, NULL);
|
|
while(head->prev != NULL) head = head->prev;
|
|
printf("%i\n", i);
|
|
}
|
|
uint64_t 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]));
|
|
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)++;
|
|
}
|