day04_01.c (4605B)
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 bool game_won = false; 114 u64 winning_score = 0; 115 116 for (u64 drawn_i = 0; drawn_i < drawn_number_count; drawn_i++) { 117 s64 drawn = drawn_numbers[drawn_i]; 118 119 for (u64 board_i = 0; board_i < board_number_count; board_i++) { 120 if (board_numbers[board_i] == drawn) { 121 board_numbers[board_i] = -1; 122 } 123 } 124 125 u8 row_count = 0; 126 u8 col_count[5] = {0}; 127 for (u64 board_i = 0; board_i < board_number_count; board_i++) { 128 u64 board = board_i / 25; 129 u64 cell = board_i % 25; 130 u64 row = cell / 5; 131 u64 col = cell % 5; 132 133 row_count += board_numbers[board_i] == -1; 134 col_count[col] += board_numbers[board_i] == -1; 135 136 if ((cell + 1) / 5 != row) { 137 if (row_count == 5) { 138 game_won = true; 139 } else { 140 row_count = 0; 141 } 142 } 143 144 if (row == 4) { 145 if (col_count[col] == 5) { 146 game_won = true; 147 } else { 148 col_count[col] = 0; 149 } 150 } 151 152 if (game_won) { 153 for (u64 i = board * 25; i < board * 25 + 25; i++) { 154 winning_score += board_numbers[i] * (board_numbers[i] != -1); 155 } 156 winning_score *= drawn; 157 goto game_over; 158 } 159 } 160 } 161 162 game_over: 163 if (game_won) { 164 printf("Winning score: %" PRIu64 "\n", winning_score); 165 } else { 166 printf("No Winning Board!\n"); 167 } 168 169 am_mem_arena_release(&a); 170 return 0; 171 }