advent2021

Advent of Code 2021 Solutions
git clone git://bsandro.tech/advent2021
Log | Files | Refs

commit 2a6c6f6869f2fecc7e160716e9bb5be8057c72ba
parent 6b31037dba861e5afcf1e7246a6ba4a32aa65675
Author: bsandro <brian.drosan@gmail.com>
Date:   Fri, 10 Dec 2021 22:18:20 +0200

Day 10, puzzle 2

Diffstat:
Mcommon/quicksort.h | 10+++++-----
Mcommon/util.h | 2+-
Mday10/puzzle.c | 96++++++++++++++++++++++++++++++++++++++++++++++++++++++-------------------------
3 files changed, 72 insertions(+), 36 deletions(-)

diff --git a/common/quicksort.h b/common/quicksort.h @@ -2,14 +2,14 @@ /* ******************* quicksort ***********************/ -static void qs_swap(int *a, int *b) { - int tmp = *a; +static void qs_swap(long long *a, long long *b) { + long long tmp = *a; *a = *b; *b = tmp; } -static long long qs_partition(int *numbers, long long low, long long high) { - int pivot = numbers[high]; +static long long qs_partition(long long *numbers, long long low, long long high) { + long long pivot = numbers[high]; long long i = low - 1; for (long long j = low; j <= high - 1; ++j) { if (numbers[j] < pivot) { @@ -21,7 +21,7 @@ static long long qs_partition(int *numbers, long long low, long long high) { return i + 1; } -static void qs(int *numbers, long long low, long long high) { +static void qs(long long *numbers, long long low, long long high) { if (low < high) { long long p = qs_partition(numbers, low, high); qs(numbers, low, p - 1); diff --git a/common/util.h b/common/util.h @@ -25,7 +25,7 @@ struct array_t { array.count, array.cap, array.elem_size, &array); \ for (size_t i = 0; i < array.count; ++i) { \ type *data = (type *)array.data; \ - printf("%d ", data[i]); \ + printf("%lld ", data[i]); \ } \ printf("\n"); \ } while (0); diff --git a/day10/puzzle.c b/day10/puzzle.c @@ -5,13 +5,10 @@ #include <errno.h> #include <string.h> #include <strings.h> -#include <stdbool.h> #include <assert.h> -#include <time.h> -#include <inttypes.h> -#include <ctype.h> #include "util.h" +#include "quicksort.h" #define STR_LEN 1024 @@ -19,7 +16,10 @@ void array_push(struct array_t *array, char bracket); char array_pop(struct array_t *array); -char validate_string(const char *str); +char validate_string(struct array_t *brackets, const char *str); +long long calc_score1(const char illegal); +long long calc_score2(struct array_t *brackets); +long long get_score2(const char c); void puzzle(const char *filename, long long *result1, long long *result2) { FILE *infile = fopen(filename, "r"); @@ -30,64 +30,61 @@ void puzzle(const char *filename, long long *result1, long long *result2) { char buf[STR_LEN] = {0}; unsigned int line_num = 0; + struct array_t scores = { .data = NULL }; + array_init(&scores, sizeof(long long), 10); *result1 = 0; *result2 = 0; while (fgets(buf, STR_LEN, infile) != NULL) { - char illegal = validate_string(buf); + struct array_t brackets = { .data = NULL }; + array_init(&brackets, sizeof(char), 10); + + char illegal = validate_string(&brackets, buf); if (illegal != 0) { - switch (illegal) { - case ')': - *result1 += 3; - break; - case ']': - *result1 += 57; - break; - case '}': - *result1 += 1197; - break; - case '>': - *result1 += 25137; - break; - } + *result1 += calc_score1(illegal); + } else { + ((long long *)scores.data)[scores.count++] = calc_score2(&brackets); } + free(brackets.data); ++line_num; bzero(buf, STR_LEN); } + long long *scores_data = (long long *)scores.data; + qs(scores_data, 0, scores.count - 1); + *result2 = scores_data[scores.count / 2]; + + free(scores.data); // mutiny! ignoring feof/ferror. fclose(infile); } -char validate_string(const char *str) { +char validate_string(struct array_t *brackets, const char *str) { size_t len = strlen(str); assert(len > 2); // at least 2 characters + EOL - struct array_t brackets = { .data = NULL }; - array_init(&brackets, sizeof(char), 10); for (size_t i = 0; i < len; ++i) { char c = str[i]; switch (c) { case '{': - array_push(&brackets, '}'); + array_push(brackets, '}'); break; case '(': - array_push(&brackets, ')'); + array_push(brackets, ')'); break; case '<': - array_push(&brackets, '>'); + array_push(brackets, '>'); break; case '[': - array_push(&brackets, ']'); + array_push(brackets, ']'); break; case '}': case ')': case '>': case ']': { - char expected = array_pop(&brackets); - if (c != expected) { + if (array_pop(brackets) != c) { return c; } break; @@ -100,7 +97,6 @@ char validate_string(const char *str) { } } - free(brackets.data); return 0; } @@ -113,6 +109,46 @@ void array_push(struct array_t *array, char bracket) { } char array_pop(struct array_t *array) { + assert(array->count > 0); char *data = (char *)array->data; return data[--array->count]; } + +long long calc_score1(const char illegal) { + switch (illegal) { + case ')': + return 3; + case ']': + return 57; + case '}': + return 1197; + case '>': + return 25137; + default: + return 0; + } +} + +long long calc_score2(struct array_t *brackets) { + long long score = 0; + while (brackets->count > 0) { + char c = array_pop(brackets); + score = score * 5 + get_score2(c); + } + return score; +} + +long long get_score2(const char c) { + switch (c) { + case ')': + return 1; + case ']': + return 2; + case '}': + return 3; + case '>': + return 4; + default: + return 0; + } +}