Skip to content

Commit

Permalink
Day 15, Part 2
Browse files Browse the repository at this point in the history
  • Loading branch information
michaeladler committed Dec 16, 2023
1 parent 11b9991 commit bec862a
Show file tree
Hide file tree
Showing 4 changed files with 93 additions and 13 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ Compiled using clang 16 and LTO.
| 12 | 347 ms | 554 ms |
| 13 | 248 µs | 486 µs |
| 14 | | 53.4 ms |
| 15 | | 1 ms |

## 🙏 Acknowledgments and Resources

Expand Down
10 changes: 6 additions & 4 deletions puzzle/day15.md
Original file line number Diff line number Diff line change
Expand Up @@ -78,8 +78,6 @@ Run the HASH algorithm on each step in the initialization sequence. What is the

Your puzzle answer was 515495.

The first half of this puzzle is complete! It provides one gold star: *

--- Part Two ---

You convince the reindeer to bring you the page; the page confirms that your HASH algorithm is working.
Expand Down Expand Up @@ -181,9 +179,13 @@ So, the above example ends up with a total focusing power of 145.

With the help of an over-enthusiastic reindeer in a hard hat, follow the initialization sequence. What is the focusing power of the resulting lens configuration?

Answer:
Your puzzle answer was 229349.

Both parts of this puzzle are complete! They provide two gold stars: **

At this point, you should return to your Advent calendar and try another puzzle.

Although it hasn't changed, you can still get your puzzle input.
If you still want to see it, you can get your puzzle input.

You can also [Shareon Twitter Mastodon] this puzzle.

91 changes: 84 additions & 7 deletions src/day15/solve.c
Original file line number Diff line number Diff line change
Expand Up @@ -11,34 +11,111 @@

#include <slice99.h>

#define MAX_LABEL_LEN 8
#define MAX_LENSES_PER_BOX 512
#define BOX_COUNT 256

typedef struct {
CharSlice99 label;
int focal;
} lens_t;

typedef struct {
lens_t item[MAX_LENSES_PER_BOX];
int item_count;
} box_t;

typedef struct {
box_t box[BOX_COUNT];
} hashmap_t;

static inline u32 hash(CharSlice99 s) {
u32 value = 0;
for (size_t i = 0; i < s.len; i++) {
char c = *CharSlice99_get(s, i);
value += c;
value *= 17;
value %= 256;
}
log_debug("hash of %.*s is %u", s.len, s.ptr, value);
for (size_t i = 0; i < s.len; i++) { value = ((value + *CharSlice99_get(s, i)) * 17) % BOX_COUNT; }
return value;
}

static inline void hashmap_upsert(hashmap_t *self, CharSlice99 label, int focal) {
u32 box_id = hash(label);
box_t *box = &self->box[box_id];
// check if we have to update an existing value
for (int i = 0; i < box->item_count; i++) {
if (CharSlice99_primitive_eq(box->item[i].label, label)) {
log_debug(">> updating box %d: label %.*s has new value %d", box_id, label.len, label.ptr, focal);
box->item[i].focal = focal;
return;
}
}
// insert new value
log_debug(">> appending to box %d: label %.*s with value %d", box_id, label.len, label.ptr, focal);
box->item_count++;
lens_t lens = {.label = label, .focal = focal};
box->item[box->item_count - 1] = lens;
}

static inline void hashmap_remove(hashmap_t *self, CharSlice99 label) {
u32 box_id = hash(label);
box_t *box = &self->box[box_id];
if (box->item_count == 0) return;
// find index of label in box
int idx = 0;
while (idx < box->item_count) {
if (CharSlice99_primitive_eq(box->item[idx].label, label)) break;
idx++;
}
if (idx == box->item_count) {
log_debug(">> box %d: label %.*s not found in hashmap, nothing to do", box_id, label.len, label.ptr);
return;
}
log_debug(">> box %d: found label %.*s at position %idx, removing it", box_id, label.len, label.ptr);
// shift neighbors
for (int i = idx + 1; i < box->item_count; i++) { box->item[i - 1] = box->item[i]; }
box->item_count--;
}

static inline void apply_instruction(hashmap_t *hm, CharSlice99 instruction) {
if (*CharSlice99_last(instruction) == '-') {
hashmap_remove(hm, CharSlice99_sub(instruction, 0, instruction.len - 1));
} else {
int i = 0;
while (*CharSlice99_get(instruction, i) != '=') i++;
CharSlice99 label = CharSlice99_sub(instruction, 0, i);
size_t pos = i + 1;
i64 focal = aoc_parse_nonnegative(instruction.ptr, &pos);
hashmap_upsert(hm, label, focal);
}
}

static inline u64 compute_focusing_power(hashmap_t *hm) {
u64 result = 0;
for (int box_number = 0; box_number < BOX_COUNT; box_number++) {
box_t *box = &hm->box[box_number];
for (int j = 0; j < box->item_count; j++) { result += (1 + box_number) * (1 + j) * box->item[j].focal; }
}
return result;
}

void solve(char *buf, size_t buf_size, Solution *result) {
u64 part1 = 0, part2 = 0;
CharSlice99 input = CharSlice99_from_ptrdiff(buf, &buf[buf_size - 2]); // no '\0', no '\n'

hashmap_t hm = {0};

size_t start = 0;
size_t pos = 0;
while (pos < input.len) {
if (*CharSlice99_get(input, pos) == ',') {
CharSlice99 s = CharSlice99_sub(input, start, pos);
part1 += hash(s);
apply_instruction(&hm, s);
start = pos + 1;
}
pos++;
}
CharSlice99 s = CharSlice99_sub(input, start, pos + 1);
part1 += hash(s);
apply_instruction(&hm, s);
part2 = compute_focusing_power(&hm);

snprintf(result->part1, sizeof(result->part1), "%lu", part1);
snprintf(result->part2, sizeof(result->part2), "%lu", part2);
Expand Down
4 changes: 2 additions & 2 deletions src/day15/solve_test.c
Original file line number Diff line number Diff line change
Expand Up @@ -16,15 +16,15 @@ CTEST(day15, example) {
Solution solution;
solve(buf, strlen(buf), &solution);
ASSERT_STR("1320", solution.part1);
// ASSERT_STR("0", solution.part2);
ASSERT_STR("145", solution.part2);
}

#ifdef HAVE_INPUTS
CTEST(day15, real) {
Solution solution;
solve_input("input/" DAY ".txt", &solution);
ASSERT_STR("515495", solution.part1);
// ASSERT_STR("0", solution.part2);
ASSERT_STR("229349", solution.part2);
}
#endif

Expand Down

0 comments on commit bec862a

Please sign in to comment.