solve day 20
This commit is contained in:
parent
1a031bf371
commit
b914c44ae0
190
day20.c
Normal file
190
day20.c
Normal file
@ -0,0 +1,190 @@
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
|
||||
#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);
|
7
main.c
7
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;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user