advent-of-code

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

day04_02.c (5105B)


      1 #if 0
      2 # Self-building c file. Invoke like: `./file.c`
      3 outdir=out
      4 input=$(basename "$0")
      5 output="$outdir"/$(basename "$0" .c)
      6 if [ "$input" -nt "$output" ];
      7 then
      8     mkdir --parents "$outdir" || exit
      9     echo "Building ${output}." || exit
     10     clang -std=c11 -Wall -Wextra -pedantic -Wno-unused-function -I../../amlibs/ "$input" -o "$output" || exit
     11 fi
     12 if [ "$1" = "-r" ];
     13 then
     14     ./"$output" "$@"
     15 fi
     16 exit
     17 #endif
     18 
     19 #include <inttypes.h>
     20 #include <stdio.h>
     21 #include <stdlib.h>
     22 #include <string.h>
     23 
     24 _Noreturn void assert_fail(const char *expr, const char *file, int line, const char *func) {
     25     fprintf(stderr, "%s:%d: %s: Assertion failed: '%s'\n", file, line, func, expr);
     26     abort();
     27 }
     28 
     29 #define AM_ENABLE_ASSERT 1
     30 #define AM_ASSERT_FAIL(expr, file, line, func) assert_fail(expr, file, line, func)
     31 #include "am_base.h"
     32 #include "am_memory.h"
     33 #include "am_list.h"
     34 #include "am_string.h"
     35 
     36 Str open_file(MemArena *arena, char *path) {
     37     FILE *f = fopen(path, "r");
     38     assert(f);
     39 
     40     s32 error = fseek(f, 0L, SEEK_END);
     41     assert(!error);
     42 
     43     s64 size = ftell(f);
     44     assert(size >= 0);
     45     rewind(f);
     46 
     47     u8 *buf = am_mem_arena_push(arena, size);
     48     assert(buf);
     49 
     50     size_t items_read = fread(buf, 1, size, f);
     51     assert(items_read == (size_t)size);
     52 
     53     error = fclose(f);
     54     assert(!error);
     55 
     56     return am_str(buf, size);
     57 }
     58 
     59 int compare_u64(const void *a, const void *b) {
     60     u64 num_a = *((u64 *)a);
     61     u64 num_b = *((u64 *)b);
     62     if (num_a == num_b) {
     63         return 0;
     64     } else if (num_a < num_b) {
     65         return -1;
     66     } else {
     67         return 1;
     68     }
     69 }
     70 
     71 s64 parse_number(Str s) {
     72     s64 number = 0;
     73     for (u64 i = 0; i < s.size; i++) {
     74         assert(s.str[i] >= '0' && s.str[i] <= '9');
     75         number = (number * 10) + (s.str[i] - '0');
     76     }
     77     return number;
     78 }
     79 
     80 int main(void) {
     81     MemArena a = am_mem_arena_create(am_mem_base_allocator_malloc());
     82     Str input = open_file(&a, "day04_input.txt");
     83 
     84     StrList split_data = am_str_split(&a, input, (u8 *)"\n ", 2);
     85     am_str_list_discard_empty(&split_data);
     86     StrList split_first_line = am_str_split(&a, split_data.first->s, (u8 *)",", 1);
     87 
     88     u64 drawn_number_count = split_first_line.node_count;
     89     u64 board_number_count = split_data.node_count - 1;
     90     assert(board_number_count % 25 == 0);
     91 
     92     s64 *drawn_numbers = AM_MEM_ARENA_PUSH_ARRAY(&a, s64, drawn_number_count);
     93     s64 *board_numbers = AM_MEM_ARENA_PUSH_ARRAY(&a, s64, board_number_count);
     94 
     95     {
     96         u64 i = 0;
     97         for (StrListNode *number = split_first_line.first; number; number = number->next) {
     98             drawn_numbers[i] = parse_number(number->s);
     99             i++;
    100         }
    101         assert(i == drawn_number_count);
    102     }
    103 
    104     {
    105         u64 i = 0;
    106         for (StrListNode *number = split_data.first->next; number; number = number->next) {
    107             board_numbers[i] = parse_number(number->s);
    108             i++;
    109         }
    110         assert(i == board_number_count);
    111     }
    112 
    113     u64 winning_score = 0;
    114     u64 win_count = 0;
    115     u64 board_count = board_number_count / 25;
    116     bool *board_win_status = AM_MEM_ARENA_PUSH_ARRAY(&a, bool, board_count);
    117     memset(board_win_status, 0, board_count * sizeof(bool));
    118 
    119     for (u64 drawn_i = 0; drawn_i < drawn_number_count; drawn_i++) {
    120         s64 drawn = drawn_numbers[drawn_i];
    121 
    122         for (u64 board_i = 0; board_i < board_number_count; board_i++) {
    123             if (board_numbers[board_i] == drawn) {
    124                 board_numbers[board_i] = -1;
    125             }
    126         }
    127 
    128         u8 row_count = 0;
    129         u8 col_count[5] = {0};
    130         for (u64 board_i = 0; board_i < board_number_count; board_i++) {
    131             u64 board = board_i / 25;
    132             if (board_win_status[board]) {
    133                 continue;
    134             }
    135 
    136             u64 cell = board_i % 25;
    137             u64 row = cell / 5;
    138             u64 col = cell % 5;
    139 
    140             row_count      += board_numbers[board_i] == -1;
    141             col_count[col] += board_numbers[board_i] == -1;
    142 
    143             bool game_won = false;
    144             if ((cell + 1) / 5 != row) {
    145                 if (row_count == 5) {
    146                     game_won = true;
    147                 }
    148                 row_count = 0;
    149             }
    150 
    151             if (row == 4) {
    152                 if (col_count[col] == 5) {
    153                     game_won = true;
    154                 }
    155                 col_count[col] = 0;
    156             }
    157 
    158             if (game_won) {
    159                 board_win_status[board] = true;
    160                 win_count++;
    161                 if (win_count == board_count) {
    162                     for (u64 i = board * 25; i < board * 25 + 25; i++) {
    163                         winning_score += board_numbers[i] * (board_numbers[i] != -1);
    164                     }
    165                     winning_score *= drawn;
    166                     goto game_over;
    167                 }
    168                 row_count = 0;
    169                 memset(col_count, 0, 5);
    170             }
    171         }
    172     }
    173 
    174 game_over:
    175     if (win_count) {
    176         printf("Winning score of last winning board: %" PRIu64 "\n", winning_score);
    177     } else {
    178         printf("No Winning Board!\n");
    179     }
    180 
    181     am_mem_arena_release(&a);
    182     return 0;
    183 }