190 lines
5.4 KiB
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;
|
|
}
|