aoc-2021/src/day_4.c

190 lines
5.4 KiB
C

#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include "puzzle_input.h"
#include "day.h"
#define BINGO_BOARD_SIZE 5
#define MAX_BINGO_BOARDS 101
#define MAX_DRAWS 100
typedef struct {
uint8_t board[BINGO_BOARD_SIZE][BINGO_BOARD_SIZE];
uint8_t matches[BINGO_BOARD_SIZE][BINGO_BOARD_SIZE];
uint8_t won;
} bingo_board_t;
typedef struct {
uint8_t num_boards;
uint8_t num_draws;
bingo_board_t boards[MAX_BINGO_BOARDS];
uint8_t draws[MAX_DRAWS];
} bingo_input_t;
parse_ret_t parse_bingo_input(char * buffer, void * data, uint16_t index) {
bingo_input_t * bingo_data = (bingo_input_t *)data;
char * tok;
parse_ret_t res;
if (index == 0) {
uint8_t draw_ndx = 0;
tok = strtok(buffer, ",");
while (tok != NULL) {
int64_t draw_val;
res = parse_long(tok, &draw_val, 10);
if (res != PARSER_OK) {
return res;
}
bingo_data->draws[draw_ndx] = (uint8_t)draw_val;
draw_ndx++;
tok = strtok(NULL, ",");
}
bingo_data->num_draws = draw_ndx+1;
}
else {
index--; // skip the draws line
tok = strtok(buffer, " ");
for (int row = 0; row < BINGO_BOARD_SIZE; row++) {
for (int col = 0; col < BINGO_BOARD_SIZE; col++) {
int64_t val;
res = parse_long(tok, &val, 10);
if (res != PARSER_OK) {
return res;
}
bingo_data->boards[index].board[row][col] = (uint8_t)val;
tok = strtok(NULL, " ");
}
}
bingo_data->num_boards++;
}
return PARSER_OK;
}
bingo_input_t bingo_input_g = {
.num_boards = 0,
.num_draws = 0,
.boards = {0},
};
uint32_t calc_score(bingo_board_t * board, uint8_t final_number) {
uint32_t sum = 0;
for (int row = 0; row < BINGO_BOARD_SIZE; row++) {
for (int col = 0; col < BINGO_BOARD_SIZE; col++) {
if (!board->matches[row][col]) {
sum += board->board[row][col];
}
}
}
return sum*final_number;
}
int day_4() {
uint16_t len;
uint8_t first_winner_found = 0;
int32_t winner_count = 0;
int32_t last_winner_ndx = -1;
int32_t last_winner_number = -1;
uint32_t score;
parse_ret_t res = read_input_multi_line("../inputs/day_4.txt", (void *)&bingo_input_g, MAX_BINGO_BOARDS+1, "", parse_bingo_input, &len);
if (res != PARSER_OK) {
printf("Failed to parse input: %d", res);
return -1;
}
for (int draw_ndx = 0; draw_ndx < bingo_input_g.num_draws; draw_ndx++) {
uint16_t draw = bingo_input_g.draws[draw_ndx];
for (int board_ndx = 0; board_ndx < bingo_input_g.num_boards; board_ndx++) {
uint8_t match_found = 0;
bingo_board_t *board = &bingo_input_g.boards[board_ndx];
for (int row = 0; row < BINGO_BOARD_SIZE; row++) {
for (int col = 0; col < BINGO_BOARD_SIZE; col++) {
if (board->board[row][col] == draw) {
board->matches[row][col] = 1;
match_found = 1;
}
if (match_found) {
break;
}
}
}
if (!board->won) {
uint8_t won_flag = 0;
for (int row = 0; row < BINGO_BOARD_SIZE; row++) {
if (board->matches[row][0] && board->matches[row][1] && board->matches[row][2] &&
board->matches[row][3] && board->matches[row][4]) {
if (!first_winner_found) {
first_winner_found = 1;
score = calc_score(board, draw);
}
winner_count++;
board->won = 1;
won_flag = 1;
break;
}
}
if (!won_flag) {
for (int col = 0; col < BINGO_BOARD_SIZE; col++) {
if (board->matches[0][col] && board->matches[1][col] && board->matches[2][col] &&
board->matches[3][col] && board->matches[4][col]) {
if (!first_winner_found) {
first_winner_found = 1;
score = calc_score(board, draw);
}
board->won = 1;
winner_count++;
break;
}
}
}
if (winner_count == bingo_input_g.num_boards) {
last_winner_ndx = board_ndx;
last_winner_number = draw;
break;
}
}
}
if (last_winner_ndx >= 0) {
break;
}
}
if (first_winner_found == 0) {
printf("Something went wrong, no winner was found\n");
return -2;
}
printf("PART 1: The final score was %d\n", score);
if (last_winner_ndx < 0) {
printf("Something went wrong, no last winner was found\n");
return -3;
}
uint32_t last_score = calc_score(&bingo_input_g.boards[last_winner_ndx], last_winner_number);
printf("PART 2: The final score of the last board was %d\n", last_score);
return 0;
}