advent-of-code

Solutions for Advent of Code.
git clone git://git.amin.space/advent-of-code.git
Log | Files | Refs | LICENSE

commit 748af4eff54eaf7ac72479c7257d72b04f581153
parent 57904a31a238de8b9bae1cec57b267d4b53c886a
Author: amin <dev@aminmesbah.com>
Date:   Sat,  4 Dec 2021 23:46:13 +0000

Solve 2021 day 4 part 2

FossilOrigin-Name: fe3ef5ff4487d6ae6077b073d9b006bbc887c32f8e0c74fe346d1c8182150819
Diffstat:
A2021/day04_02.c | 182+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 182 insertions(+), 0 deletions(-)

diff --git a/2021/day04_02.c b/2021/day04_02.c @@ -0,0 +1,182 @@ +#if 0 +# Self-building c file. Invoke like: `./file.c` +outdir=out +input=$(basename "$0") +output="$outdir"/$(basename "$0" .c) +if [ "$input" -nt "$output" ]; +then + mkdir --parents "$outdir" || exit + echo "Building ${output}." || exit + clang -std=c11 -Wall -Wextra -pedantic -Wno-unused-function "$input" -o "$output" || exit +fi +if [ "$1" = "-r" ]; +then + ./"$output" "$@" +fi +exit +#endif + +#include <inttypes.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +_Noreturn void assert_fail(const char *expr, const char *file, int line, const char *func) { + fprintf(stderr, "%s:%d: %s: Assertion failed: '%s'\n", file, line, func, expr); + abort(); +} + +#define AM_ENABLE_ASSERT 1 +#define AM_ASSERT_FAIL(expr, file, line, func) assert_fail(expr, file, line, func) +#include "am_base.h" +#include "am_memory.h" +#include "am_list.h" +#include "am_string.h" + +Str open_file(MemArena *arena, char *path) { + FILE *f = fopen(path, "r"); + assert(f); + + s32 error = fseek(f, 0L, SEEK_END); + assert(!error); + + s64 size = ftell(f); + assert(size >= 0); + rewind(f); + + u8 *buf = am_mem_arena_push(arena, size); + assert(buf); + + size_t items_read = fread(buf, 1, size, f); + assert(items_read == (size_t)size); + + error = fclose(f); + assert(!error); + + return am_str(buf, size); +} + +int compare_u64(const void *a, const void *b) { + u64 num_a = *((u64 *)a); + u64 num_b = *((u64 *)b); + if (num_a == num_b) { + return 0; + } else if (num_a < num_b) { + return -1; + } else { + return 1; + } +} + +s64 parse_number(Str s) { + s64 number = 0; + for (u64 i = 0; i < s.size; i++) { + assert(s.str[i] >= '0' && s.str[i] <= '9'); + number = (number * 10) + (s.str[i] - '0'); + } + return number; +} + +int main(void) { + MemArena a = am_mem_arena_create(am_mem_base_allocator_malloc()); + Str input = open_file(&a, "day04_input.txt"); + + StrList split_data = am_str_split(&a, input, (u8 *)"\n ", 2); + StrList split_first_line = am_str_split(&a, split_data.first->s, (u8 *)",", 1); + + u64 drawn_number_count = split_first_line.node_count; + u64 board_number_count = split_data.node_count - 1; + assert(board_number_count % 25 == 0); + + s64 *drawn_numbers = AM_MEM_ARENA_PUSH_ARRAY(&a, s64, drawn_number_count); + s64 *board_numbers = AM_MEM_ARENA_PUSH_ARRAY(&a, s64, board_number_count); + + { + u64 i = 0; + for (StrListNode *number = split_first_line.first; number; number = number->next) { + drawn_numbers[i] = parse_number(number->s); + i++; + } + assert(i == drawn_number_count); + } + + { + u64 i = 0; + for (StrListNode *number = split_data.first->next; number; number = number->next) { + board_numbers[i] = parse_number(number->s); + i++; + } + assert(i == board_number_count); + } + + u64 winning_score = 0; + u64 win_count = 0; + u64 board_count = board_number_count / 25; + bool *board_win_status = AM_MEM_ARENA_PUSH_ARRAY(&a, bool, board_count); + memset(board_win_status, 0, board_count * sizeof(bool)); + + for (u64 drawn_i = 0; drawn_i < drawn_number_count; drawn_i++) { + s64 drawn = drawn_numbers[drawn_i]; + + for (u64 board_i = 0; board_i < board_number_count; board_i++) { + if (board_numbers[board_i] == drawn) { + board_numbers[board_i] = -1; + } + } + + u8 row_count = 0; + u8 col_count[5] = {0}; + for (u64 board_i = 0; board_i < board_number_count; board_i++) { + u64 board = board_i / 25; + if (board_win_status[board]) { + continue; + } + + u64 cell = board_i % 25; + u64 row = cell / 5; + u64 col = cell % 5; + + row_count += board_numbers[board_i] == -1; + col_count[col] += board_numbers[board_i] == -1; + + bool game_won = false; + if ((cell + 1) / 5 != row) { + if (row_count == 5) { + game_won = true; + } + row_count = 0; + } + + if (row == 4) { + if (col_count[col] == 5) { + game_won = true; + } + col_count[col] = 0; + } + + if (game_won) { + board_win_status[board] = true; + win_count++; + if (win_count == board_count) { + for (u64 i = board * 25; i < board * 25 + 25; i++) { + winning_score += board_numbers[i] * (board_numbers[i] != -1); + } + winning_score *= drawn; + goto game_over; + } + row_count = 0; + memset(col_count, 0, 5); + } + } + } + +game_over: + if (win_count) { + printf("Winning score of last winning board: %" PRIu64 "\n", winning_score); + } else { + printf("No Winning Board!\n"); + } + + am_mem_arena_release(&a); + return 0; +}