Skip to content

Commit

Permalink
refactor: Day12 use slice99 library
Browse files Browse the repository at this point in the history
  • Loading branch information
michaeladler committed Dec 14, 2023
1 parent 476d553 commit 96c1159
Show file tree
Hide file tree
Showing 4 changed files with 1,121 additions and 35 deletions.
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ Compiled using clang 16 and LTO.
| 9 | 256 µs | 464 µs |
| 10 | 5.8 ms | 16.4 ms |
| 11 | 980 µs | 1.7 ms |
| 12 | 416 ms | 554 ms |
| 12 | 347 ms | 554 ms |

## 🙏 Acknowledgments and Resources

Expand All @@ -67,3 +67,4 @@ Special thanks to the authors of these very useful C resources:
- [Sort](https://github.com/swenson/sort/) - A collection of sorting algorithms implemented in C.
- [str](https://github.com/maxim2266/str) - yet another string library for C language.
- [xxhash](https://github.com/Cyan4973/xxHash) - Extremely fast non-cryptographic hash algorithm.
- [slice99](https://github.com/Hirrolot/slice99) - Memory slices for C99.
2 changes: 1 addition & 1 deletion meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ endif

c = meson.get_compiler('c')

inc_dirs = ['include', 'vendor/ctl', 'vendor/sort', 'vendor/log', 'vendor/str']
inc_dirs = ['include', 'vendor/ctl', 'vendor/sort', 'vendor/log', 'vendor/str', 'vendor/slice99']

m_dep = c.find_library('m', required : false)
xxhash_dep = c.find_library('xxhash', required : true)
Expand Down
61 changes: 28 additions & 33 deletions src/day12/solve.c
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
#include <stdbool.h>
#include <stddef.h>

#include <slice99.h>
#include <xxhash.h>

#define OPERATIONAL '.'
Expand All @@ -25,75 +26,68 @@
#define MAX_UNKNOWNS 64

typedef struct {
char *spring;
int spring_size;

int size[MAX_GROUPS]; /* immutable so we can just copy the pointer */
int size_count;
Slice99 spring;
Slice99 size;
int group_size;

size_t value;
} CacheItem;

size_t CacheItem_hash(CacheItem *item) {
XXH64_hash_t spring_hash = XXH3_64bits(item->spring, item->spring_size);

size_t result = 17;
result = 31 * result + item->spring_size;
result = 31 * result + spring_hash;
result = 31 * result + item->size_count;
for (int i = 0; i < item->size_count; i++) { result = 31 * result + item->size[i]; }
result = 31 * result + XXH3_64bits(item->spring.ptr, item->spring.len);
result = 31 * result + XXH3_64bits(item->size.ptr, item->size.len);
result = 31 * result + item->group_size;
return result;
}

int CacheItem_equal(CacheItem *lhs, CacheItem *rhs) {
return lhs->size_count == rhs->size_count && lhs->group_size == rhs->group_size &&
lhs->spring_size == rhs->spring_size && memcmp(lhs->size, rhs->size, lhs->size_count) == 0 &&
memcmp(lhs->spring, rhs->spring, lhs->spring_size) == 0;

return lhs->group_size == rhs->group_size && Slice99_primitive_eq(lhs->size, rhs->size) &&
Slice99_primitive_eq(lhs->spring, rhs->spring);
}

#define P
#define T CacheItem
#include <ust.h>

static size_t find_solutions(ust_CacheItem *cache, char *spring, int spring_size, int *size, int size_count,
int group_size) {
static size_t find_solutions(ust_CacheItem *cache, Slice99 spring, Slice99 size, int group_size) {
// check cache for answer
CacheItem item = {.spring = spring, .spring_size = spring_size, .size_count = size_count, .group_size = group_size};
memcpy(&item.size, size, size_count);
CacheItem item = {.spring = spring, .size = size, .group_size = group_size};

ust_CacheItem_node *node = ust_CacheItem_find(cache, item);
if (node != NULL) { return node->key.value; }

if (spring[0] == '\0') {
if (size_count == 1 && size[0] == group_size) { return 1; }
if (size_count == 0 && group_size == 0) { return 1; }
if (Slice99_is_empty(spring)) {
if (size.len == 1 && *(int *)Slice99_first(size) == group_size) { return 1; }
if (Slice99_is_empty(size) && group_size == 0) { return 1; }
return 0;
}

size_t count = 0;
char symbols[3];
if (spring[0] == '?') {
char first = *(char *)Slice99_first(spring);
if (first == '?') {
symbols[0] = OPERATIONAL;
symbols[1] = DAMAGED;
symbols[2] = '\0'; // marker
} else {
symbols[0] = spring[0];
symbols[0] = first;
symbols[1] = '\0';
}
for (int i = 0; symbols[i] != '\0'; i++) {
if (symbols[i] == DAMAGED) { // expand group
count += find_solutions(cache, &spring[1], spring_size - 1, size, size_count, group_size + 1);
count += find_solutions(cache, Slice99_advance(spring, 1), size, group_size + 1);
continue;
}
assert(symbols[i] == OPERATIONAL);
if (group_size > 0) { // current group has ended now
if (size_count > 0 && size[0] == group_size) { // only continue if group size matches the expected one
count += find_solutions(cache, &spring[1], spring_size - 1, &size[1], size_count - 1, 0);
if (group_size > 0) { // current group has ended now
if (!Slice99_is_empty(size) &&
*(int *)Slice99_first(size) == group_size) { // only continue if group size matches the expected one
count += find_solutions(cache, Slice99_advance(spring, 1), Slice99_advance(size, 1), 0);
}
} else {
count += find_solutions(cache, &spring[1], spring_size - 1, size, size_count, 0);
count += find_solutions(cache, Slice99_advance(spring, 1), size, 0);
}
}

Expand Down Expand Up @@ -123,11 +117,11 @@ void solve(const char *buf, size_t buf_size, Solution *result) {
if (buf[pos] == ',') pos++;
}

spring[spring_count] = '\0'; // for printing

{ // part 1
ust_CacheItem cache = ust_CacheItem_init(CacheItem_hash, CacheItem_equal);
size_t count = find_solutions(&cache, spring, spring_count, size, size_count, 0);
Slice99 spring_slice = Slice99_from_typed_ptr(spring, spring_count);
Slice99 size_slice = Slice99_from_typed_ptr(size, size_count);
size_t count = find_solutions(&cache, spring_slice, size_slice, 0);
part1 += count;
ust_CacheItem_free(&cache);
}
Expand All @@ -148,9 +142,10 @@ void solve(const char *buf, size_t buf_size, Solution *result) {
for (int j = 0; j < size_count; j++) { big_size[big_size_count++] = size[j]; }
}
assert(big_size_count == 5 * size_count);
big_spring[big_spring_count] = '\0'; // for printing

size_t count = find_solutions(&cache, big_spring, big_spring_count, big_size, big_size_count, 0);
Slice99 big_spring_slice = Slice99_from_typed_ptr(big_spring, big_spring_count);
Slice99 big_size_slice = Slice99_from_typed_ptr(big_size, big_size_count);
size_t count = find_solutions(&cache, big_spring_slice, big_size_slice, 0);
part2 += count;

ust_CacheItem_free(&cache);
Expand Down
Loading

0 comments on commit 96c1159

Please sign in to comment.