From 861826d3ffcf75f67d8e207a8ec65ab0c6c4d80a Mon Sep 17 00:00:00 2001 From: Rokas Puzonas Date: Sun, 11 Jun 2023 16:27:21 +0300 Subject: [PATCH] solve day 13 --- aoc.h | 1 + day12.c | 3 +- day13.c | 230 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ main.c | 5 +- 4 files changed, 236 insertions(+), 3 deletions(-) create mode 100644 day13.c diff --git a/aoc.h b/aoc.h index 4842da2..05c781e 100644 --- a/aoc.h +++ b/aoc.h @@ -2,6 +2,7 @@ #define AOC_H_ #include +#include typedef void (*solution_cb)(void*); typedef void* (*parse_cb)(char** lines, int count); diff --git a/day12.c b/day12.c index dcf595d..743e9e7 100644 --- a/day12.c +++ b/day12.c @@ -1,12 +1,11 @@ #include #include #include -#include #include +#include "aoc.h" #include "types.h" #include "point.h" -#include "aoc.h" typedef struct { u8 *map; diff --git a/day13.c b/day13.c new file mode 100644 index 0000000..18acf16 --- /dev/null +++ b/day13.c @@ -0,0 +1,230 @@ +#include +#include +#include +#include +#include + +#include "types.h" +#include "aoc.h" + +typedef struct day13_packet *day13_packet_ptr; + +struct day13_packet { + bool is_number; + union { + u8 number; + struct { + day13_packet_ptr list; + size_t list_size; + }; + }; +}; + +typedef struct { + struct day13_packet left; + struct day13_packet right; +} day13_packet_pair; + +typedef struct { + day13_packet_pair* pairs; + size_t count; +} day13_packet_pairs; + +static bool day13_is_digit(char c) +{ + return '0' <= c && c <= '9'; +} + +static size_t day13_parse_packet(struct day13_packet *result, char *packet) +{ + size_t bytes_read = 0; + + if (packet[0] == '[') { + bytes_read++; + result->is_number = false; + result->list_size = 0; + result->list = NULL; + if (packet[1] != ']') { + while (true) { + result->list = realloc(result->list, sizeof(struct day13_packet)*(result->list_size+1)); + bytes_read += day13_parse_packet(&result->list[result->list_size], packet+bytes_read); + result->list_size++; + + if (packet[bytes_read] == ',') { + bytes_read++; + continue; + } + if (packet[bytes_read] == ']') break; + assert(false && "fuck"); + } + } + bytes_read++; + } else if (day13_is_digit(packet[0])) { + bytes_read++; + result->is_number = true; + result->number = (packet[0] - '0'); + for (int i = 1; i < strlen(packet); i++) { + if (!day13_is_digit(packet[i])) break; + result->number *= 10; + result->number += (packet[i] - '0'); + bytes_read++; + } + } else { + assert(false && "Failed to parse packet"); + } + + return bytes_read; +} + +static void printf_day13_packet(struct day13_packet *packet) +{ + if (packet->is_number) { + printf("%d", packet->number); + } else { + printf("["); + if (packet->list_size > 0) { + for (int i = 0; i < packet->list_size-1; i++) { + printf_day13_packet(&packet->list[i]); + printf(","); + } + printf_day13_packet(&packet->list[packet->list_size-1]); + } + printf("]"); + } +} + +static void *day13_parse(char **lines, int line_count) +{ + size_t n = (line_count+1)/3; + day13_packet_pair *pairs = malloc(sizeof(day13_packet_pair)*n); + + for (int i = 0; i < n; i++) + { + day13_parse_packet(&pairs[i].left , lines[3*i+0]); + day13_parse_packet(&pairs[i].right, lines[3*i+1]); + } + + day13_packet_pairs *result = malloc(sizeof(day13_packet_pairs)); + result->pairs = pairs; + result->count = n; + return result; +} + +// Return values: +// -1 = left is lower +// 0 = equal +// 1 = right is lower +static int day13_compare(struct day13_packet *left, struct day13_packet *right) +{ + if (left->is_number && right->is_number) { + if (left->number == right->number) { + return 0; + } else if (left->number < right->number) { + return -1; + } else { + return 1; + } + } else if (!left->is_number && !right->is_number) { + for (int i = 0; i < MIN(left->list_size, right->list_size); i++) { + int item_result = day13_compare(&left->list[i], &right->list[i]); + if (item_result != 0) { + return item_result; + } + } + if (left->list_size < right->list_size) { + return -1; + } else if (left->list_size > right->list_size) { + return 1; + } + } else if (left->is_number && !right->is_number) { + struct day13_packet packet = { + .is_number = false, + .list = left, + .list_size = 1 + }; + return day13_compare(&packet, right); + } else if (!left->is_number && right->is_number) { + struct day13_packet packet = { + .is_number = false, + .list = right, + .list_size = 1 + }; + return day13_compare(left, &packet); + } + return 0; +} + +static void day13_part1(void *p) +{ + day13_packet_pairs *pairs = (day13_packet_pairs*)p; + int result = 0; + for (int i = 0; i < pairs->count; i++) { + if (day13_compare(&pairs->pairs[i].left, &pairs->pairs[i].right) == -1) { + result += (i+1); + } + } + printf("Answer: %d\n", result); +} + +static int day13_find_packet(struct day13_packet **packets, size_t count, struct day13_packet *target) +{ + for (int i = 0; i < count; i++) { + if (packets[i] == target) { + return i; + } + } + return -1; +} + +static void day13_swap(struct day13_packet **A, struct day13_packet **B) +{ + struct day13_packet *C = *A; + *A = *B; + *B = C; +} + +// bubble sort +static void day13_sort_packets(struct day13_packet **packets, size_t count) +{ + for (int i = 0; i < count-1; i++) { + for (int j = i+1; j < count; j++) { + int cmp = day13_compare(packets[i], packets[j]); + if (cmp == 1) { + day13_swap(&packets[i], &packets[j]); + } + } + } +} + +static void day13_part2(void *p) +{ + day13_packet_pairs *pairs = (day13_packet_pairs*)p; + + size_t packet_count = pairs->count*2 + 2; + struct day13_packet **packets = malloc(sizeof(struct day13_packet*)*packet_count); + + // insert divider [[2]] + struct day13_packet divider1; + day13_parse_packet(÷r1, "[[2]]"); + packets[0] = ÷r1; + + // insert divider [[6]] + struct day13_packet divider2; + day13_parse_packet(÷r2, "[[6]]"); + packets[1] = ÷r2; + + // insert packets from `pairs.pairs` + for (int i = 0; i < pairs->count; i++) { + packets[2 + i*2+0] = &pairs->pairs[i].left; + packets[2 + i*2+1] = &pairs->pairs[i].right; + } + + day13_sort_packets(packets, packet_count); + + int divider1_idx = day13_find_packet(packets, packet_count, ÷r1); + int divider2_idx = day13_find_packet(packets, packet_count, ÷r2); + int answer = (divider1_idx+1) * (divider2_idx+1); + printf("Answer: %d\n", answer); +} + +ADD_SOLUTION(13, day13_parse, day13_part1, day13_part2); diff --git a/main.c b/main.c index d139258..a7f837e 100644 --- a/main.c +++ b/main.c @@ -21,6 +21,7 @@ #include "day10.c" #include "day11.c" #include "day12.c" +#include "day13.c" Solution *find_solution(int day) { @@ -170,10 +171,12 @@ int main(int argc, char** argv) { fclose(f); + uint64_t start_time = get_current_time_us(); void* parsed = solution->parse(lines, line_count); + printf("Parsing took %ldus\n", get_current_time_us() - start_time); printf("part1:\n"); - uint64_t start_time = get_current_time_us(); + start_time = get_current_time_us(); solution->part1(parsed); printf("Part 1 took %ldus\n\n", get_current_time_us() - start_time);