From b914c44ae050705c99058f75feda5d6f78b6f35d Mon Sep 17 00:00:00 2001 From: Rokas Puzonas Date: Sat, 8 Jul 2023 00:55:53 +0300 Subject: [PATCH] solve day 20 --- day20.c | 190 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ main.c | 7 ++- 2 files changed, 195 insertions(+), 2 deletions(-) create mode 100644 day20.c diff --git a/day20.c b/day20.c new file mode 100644 index 0000000..7eda161 --- /dev/null +++ b/day20.c @@ -0,0 +1,190 @@ +#include +#include + +#include "types.h" +#include "aoc.h" + +typedef struct { + i64 *numbers; + u32 count; +} day20_data; + +typedef struct day20_node *day20_node_ptr; +struct day20_node { + i64 value; + day20_node_ptr next; + day20_node_ptr prev; +}; + +static void* day20_parse(char** lines, int line_count) +{ + day20_data *data = malloc(sizeof(day20_data)); + data->numbers = malloc(sizeof(i64) * line_count); + data->count = line_count; + + for (int i = 0; i < line_count; i++) { + data->numbers[i] = strtol(lines[i], NULL, 10); + } + + return data; +} + +static struct day20_node *day20_list_alloc(i64 *values, u32 count) +{ + struct day20_node *start = calloc(1, sizeof(struct day20_node)); + start->value = values[0]; + start->next = NULL; + + struct day20_node *prev = start; + for (int i = 1; i < count; i++) { + struct day20_node *curr = calloc(1, sizeof(struct day20_node)); + curr->value = values[i]; + curr->prev = prev; + prev->next = curr; + prev = curr; + } + + prev->next = start; + start->prev = prev; + + return start; +} + +static void day20_list_free(struct day20_node *list) +{ + struct day20_node *curr = list; + curr->prev->next = NULL; + while (curr) { + struct day20_node *next = curr->next; + curr->next = NULL; + free(curr); + curr = next; + } +} + +static struct day20_node *day20_list_get(struct day20_node *list, i64 nth, u32 list_size) +{ + struct day20_node *curr = list; + if (nth > 0) { + for (int i = 0; i < nth % list_size; i++) { + curr = curr->next; + } + } else if (nth < 0) { + for (int i = 0; i < (-nth+1) % list_size; i++) { + curr = curr->prev; + } + } + return curr; +} + +static struct day20_node *day20_list_find(struct day20_node *list, i64 value) +{ + struct day20_node *curr = list; + do { + if (curr->value == value) { + return curr; + } + curr = curr->next; + } while (curr != list); + return NULL; +} + +static void day20_node_remove(struct day20_node *node) +{ + struct day20_node *prev = node->prev; + struct day20_node *next = node->next; + + prev->next = next; + next->prev = prev; +} + +static void day20_node_insert_after(struct day20_node *node, struct day20_node *new_node) +{ + struct day20_node *next = node->next; + + new_node->prev = node; + new_node->next = next; + node->next = new_node; + next->prev = new_node; +} + +static void day20_print_list(struct day20_node *list) +{ + struct day20_node *curr = list; + do { + printf("%ld ", curr->value); + curr = curr->next; + } while (curr != list); + printf("\n"); +} + +static void day20_mix_list(struct day20_node **order, u32 count) +{ + for (int i = 0; i < count; i++) { + struct day20_node *curr = order[i]; + if (curr->value == 0) continue; + + day20_node_remove(curr); + struct day20_node *other = day20_list_get(curr, curr->value, count-1); + day20_node_insert_after(other, curr); + } +} + +static void day20_part1(void *p) +{ + day20_data *data = (day20_data*)p; + + struct day20_node *list = day20_list_alloc(data->numbers, data->count); + + struct day20_node *order[data->count]; + order[0] = list; + for (int i = 1; i < data->count; i++) + { + order[i] = order[i-1]->next; + } + + day20_mix_list(order, data->count); + + i64 answer = 0; + struct day20_node *zero_node = day20_list_find(list, 0); + answer += day20_list_get(zero_node, 1000, data->count)->value; + answer += day20_list_get(zero_node, 2000, data->count)->value; + answer += day20_list_get(zero_node, 3000, data->count)->value; + printf("%ld\n", answer); + + day20_list_free(list); +} + +static void day20_part2(void *p) +{ + day20_data *data = (day20_data*)p; + + i64 decryption_key = 811589153; + for (int i = 0; i < data->count; i++) { + data->numbers[i] *= decryption_key; + } + + struct day20_node *list = day20_list_alloc(data->numbers, data->count); + + struct day20_node *order[data->count]; + order[0] = list; + for (int i = 1; i < data->count; i++) + { + order[i] = order[i-1]->next; + } + + for (int i = 0; i < 10; i++) { + day20_mix_list(order, data->count); + } + + i64 answer = 0; + struct day20_node *zero_node = day20_list_find(list, 0); + answer += day20_list_get(zero_node, 1000, data->count)->value; + answer += day20_list_get(zero_node, 2000, data->count)->value; + answer += day20_list_get(zero_node, 3000, data->count)->value; + printf("%ld\n", answer); + + day20_list_free(list); +} + +ADD_SOLUTION(20, day20_parse, day20_part1, day20_part2); diff --git a/main.c b/main.c index e4110c4..f6f913e 100644 --- a/main.c +++ b/main.c @@ -28,6 +28,7 @@ #include "day17.c" #include "day18.c" #include "day19.c" +#include "day20.c" Solution *find_solution(int day) { @@ -184,12 +185,14 @@ int main(int argc, char** argv) { printf("part1:\n"); start_time = get_current_time_us(); solution->part1(parsed); - printf("Part 1 took %ldus\n\n", get_current_time_us() - start_time); + u64 part1_duration = get_current_time_us() - start_time; + printf("Part 1 took %ldus (%ldms)\n\n", part1_duration, part1_duration/1000); printf("part2:\n"); start_time = get_current_time_us(); solution->part2(parsed); - printf("Part 2 took %ldus\n", get_current_time_us() - start_time); + u64 part2_duration = get_current_time_us() - start_time; + printf("Part 2 took %ldus (%ldms)\n", part2_duration, part2_duration/1000); return 0; }