This commit is contained in:
Georgios Samaras 2024-12-11 16:00:27 +01:00
parent 56a7b1418f
commit b461a7d737
4 changed files with 167 additions and 0 deletions

1
day-11/input.txt Normal file
View File

@ -0,0 +1 @@
3935565 31753 437818 7697 5 38 0 123

164
day-11/main.c Normal file
View File

@ -0,0 +1,164 @@
#include "aoc.h"
#include <stdlib.h>
static inline bool
is_even(i64 x) { return (x & 1) == 0; }
static inline i64
count_digits(i64 x) {
ASSERT(x >= 0);
if (x < 10ull) return 1;
if (x < 100ull) return 2;
if (x < 1000ull) return 3;
if (x < 10000ull) return 4;
if (x < 100000ull) return 5;
if (x < 1000000ull) return 6;
if (x < 10000000ull) return 7;
if (x < 100000000ull) return 8;
if (x < 1000000000ull) return 9;
if (x < 10000000000ull) return 10;
if (x < 100000000000ull) return 11;
if (x < 1000000000000ull) return 12;
if (x < 10000000000000ull) return 13;
if (x < 100000000000000ull) return 14;
if (x < 1000000000000000ull) return 15;
if (x < 10000000000000000ull) return 16;
if (x < 100000000000000000ull) return 17;
if (x < 1000000000000000000ull) return 18;
if (x < 10000000000000000000ull) return 19;
return 20;
}
static const i64
POWERS_OF_TEN[] = {
1ull,
10ull,
100ull,
1000ull,
10000ull,
100000ull,
1000000ull,
10000000ull,
100000000ull,
1000000000ull,
10000000000ull,
100000000000ull,
1000000000000ull,
10000000000000ull,
100000000000000ull,
1000000000000000ull,
10000000000000000ull,
100000000000000000ull,
1000000000000000000ull,
10000000000000000000ull,
};
static u64
hash_stone_iterations(i64 stone, i32 iterations) {
return ((u64) stone * 73856093ull) ^ ((u64) iterations * 2654435761ull);
}
#define CACHE_SIZE (1 << 18) // empirically determined
_Static_assert((CACHE_SIZE & (CACHE_SIZE - 1)) == 0, "CACHE_SIZE must be a power of 2");
#define CACHE_MASK (CACHE_SIZE - 1)
typedef struct CacheSlot {
struct CacheSlot *next;
i64 stone;
i32 iterations;
i64 result;
} CacheSlot;
typedef struct Cache {
CacheSlot *slots[CACHE_SIZE];
Arena *arena;
} Cache;
static void
cache_init(Cache *cache, Arena *arena) {
cache->arena = arena;
}
static bool
cache_get(Cache *cache, i64 stone, i32 iterations, i64 *result) {
u64 hash = hash_stone_iterations(stone, iterations);
u64 index = hash & CACHE_MASK;
for (CacheSlot *slot = cache->slots[index]; slot; slot = slot->next) {
if (slot->stone == stone && slot->iterations == iterations) {
*result = slot->result;
return true;
}
}
return false;
}
static void
cache_put(Cache *cache, i64 stone, i32 iterations, i64 result) {
u64 hash = hash_stone_iterations(stone, iterations);
u64 index = hash & CACHE_MASK;
for (CacheSlot *slot = cache->slots[index]; slot; slot = slot->next) {
if (slot->stone == stone && slot->iterations == iterations) {
slot->result = result;
return;
}
}
// not found
CacheSlot *slot = ARENA_ALLOC(cache->arena, CacheSlot);
slot->stone = stone;
slot->iterations = iterations;
slot->result = result;
slot->next = cache->slots[index];
cache->slots[index] = slot;
}
static i64
evolve(Cache *cache, i64 stone, i32 iterations) {
if (iterations == 0) {
return 1;
}
else {
i64 result = 0;
if (cache_get(cache, stone, iterations, &result)) {
return result;
}
else if (stone == 0) {
result = evolve(cache, 1, iterations - 1);
}
else {
i64 digit_count = count_digits(stone);
if (is_even(digit_count)) {
i64 pot = POWERS_OF_TEN[digit_count / 2];
i64 left = stone / pot;
i64 right = stone % pot;
result = evolve(cache, left, iterations - 1) + evolve(cache, right, iterations - 1);
}
else {
i64 new_stone = stone * 2024;
result = evolve(cache, new_stone, iterations - 1);
}
}
cache_put(cache, stone, iterations, result);
return result;
}
}
int main(int argc, char **argv) {
Arena *arena = make_arena(Megabytes(16));
str input = str_trim(read_file(arena, argv[1]));
Cache *cache = ARENA_ALLOC(arena, Cache);
cache_init(cache, arena);
str iter = input;
str token;
i64 part_1 = 0;
i64 part_2 = 0;
while ((token = str_next_token(&iter, STR(" "))).len > 0) {
i64 stone = parse_i64(token, *arena);
part_1 += evolve(cache, stone, 25);
part_2 += evolve(cache, stone, 75);
}
printf("%ld\n", part_1);
printf("%ld\n", part_2);
}

1
day-11/test.txt Normal file
View File

@ -0,0 +1 @@
0 1 10 99 999

1
day-11/test2.txt Normal file
View File

@ -0,0 +1 @@
125 17