You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

283 lines
6.4 KiB
C

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <stdbool.h>
#include <string.h>
#include <ctype.h>
#include <inttypes.h>
#define RESET "\033[0m"
#define RED "\033[31m"
#define DEBUG
#define INPUT_FILE ("../input.txt")
#define MAX_NUMBERS_DRAWN (1024)
#define MAX_BOARDS (256)
/*
Think of the win_conditions array as this table of win conditions
WIN CONDITIONS
* x x x x x * x x x x x * x x x x x * x x x x x *
* x x x x x * x x x x x * x x x x x * x x x x x *
* x x x x x * x x x x x * x x x x x * x x x x x *
* x x x x x * x x x x x * x x x x x * x x x x x *
* x x x x x * x x x x x * x x x x x * x x x x x *
* * * * * x x x x x x x x x x x x x x x x x x x x
x x x x x * * * * * x x x x x x x x x x x x x x x
x x x x x x x x x x * * * * * x x x x x x x x x x
x x x x x x x x x x x x x x x * * * * * x x x x x
x x x x x x x x x x x x x x x x x x x x * * * * *
*/
const uint32_t win_conditions[10] =
{
0b00000000000100001000010000100001,
0b00000000001000010000100001000010,
0b00000000010000100001000010000100,
0b00000000100001000010000100001000,
0b00000001000010000100001000010000,
0b00000000000000000000000000011111,
0b00000000000000000000001111100000,
0b00000000000000000111110000000000,
0b00000000000011111000000000000000,
0b00000001111100000000000000000000
};
typedef struct board_t
{
uint8_t matrix[5][5];
// idk what to call this
// its just a u32, if the number in a slot x has been drawn,
// then a 1 will be in that bit position inside of this number
// example: slot[3][4] = (3 * 5) + 4 = 19, if this slot has been drawn,
// bit position 19 will be a 1
uint32_t output;
uint8_t most_recently_drawn;
// if true, its got a bingo
bool bingo_status;
}board_t;
bool bingo_board_win_check(const board_t* board);
int bingo_board_compute_answer(const board_t* board);
bool bingo_add_new_entry(board_t* board, uint8_t num);
void print_bingo_board(const board_t* board);
int main(void)
{
int p1_answer = 0;
int p2_answer = 0;
board_t bingo_bank[MAX_BOARDS];
uint16_t bingo_board_count = 0;
uint8_t bingo_drawn_numbers[MAX_NUMBERS_DRAWN];
uint16_t bingo_drawn_numbers_ct = 0;
memset(bingo_bank, 0, sizeof(board_t) * MAX_BOARDS);
FILE* fp = fopen(INPUT_FILE, "r");
if(fp == NULL)
{
printf("Failed to open input file for reading...\n");
exit(-1);
}
size_t len;
ssize_t rc;
char* line = NULL;
rc = getline(&line, &len, fp);
const char* delim = ", \r\n";
char* tok = strtok(line, delim);
while(tok != NULL)
{
bingo_drawn_numbers[bingo_drawn_numbers_ct++] =
strtoul(tok, NULL, 10);
tok = strtok(NULL, delim);
}
while(bingo_board_count < MAX_BOARDS && fp != NULL)
{
// continue to numbers....
char c = '\0';
while(!isdigit(c) && !feof(fp))
{
c = fgetc(fp);
}
if(feof(fp))
{
break;
}
fseek(fp, -1, SEEK_CUR);
for(int ind = 0; ind < 5; ind++)
{
rc = getline(&line, &len, fp);
if(rc < 0)
{
printf("some error while parsing");
exit(-1);
}
sscanf(line,
"%2" SCNu8 " "
"%2" SCNu8 " "
"%2" SCNu8 " "
"%2" SCNu8 " "
"%2" SCNu8 " ",
&bingo_bank[bingo_board_count].matrix[ind][0],
&bingo_bank[bingo_board_count].matrix[ind][1],
&bingo_bank[bingo_board_count].matrix[ind][2],
&bingo_bank[bingo_board_count].matrix[ind][3],
&bingo_bank[bingo_board_count].matrix[ind][4]);
}
bingo_board_count++;
}
#ifdef DEBUG
for(int ind = 0; ind < bingo_board_count; ind++)
{
print_bingo_board(&bingo_bank[ind]);
}
#endif
for(int ind = 0; ind < bingo_drawn_numbers_ct; ind++)
{
#ifdef DEBUG
printf("... drawing number ... Number #%d!\n", bingo_drawn_numbers[ind]);
#endif
for(int board = 0; board < bingo_board_count; board++)
{
if(bingo_add_new_entry(&bingo_bank[board], bingo_drawn_numbers[ind]))
{
p1_answer = bingo_board_compute_answer(&bingo_bank[board]);
#ifdef DEBUG
print_bingo_board(&bingo_bank[board]);
#endif
break;
}
#ifdef DEBUG
print_bingo_board(&bingo_bank[board]);
#endif
}
if(p1_answer != 0)
{
break;
}
}
printf("Answer for part 1: %d\n", p1_answer);
printf("Part 2... Begin!\n");
// to do part 2, we're going to completely restart
// we could just keep going off of the above for loop to save time
// but i want the solutions to be as separate as possible
// so lets reset the count
for(int board = 0; board < bingo_board_count; board++)
{
bingo_bank[board].output = 0;
}
// now we restart the process
int completed_boards = 0;
for(int ind = 0; ind < bingo_drawn_numbers_ct; ind++)
{
#ifdef DEBUG
printf("... drawing number ... #%d!\n", bingo_drawn_numbers[ind]);
#endif
for(int board = 0; board < bingo_board_count; board++)
{
if(bingo_bank[board].bingo_status)
{
continue;
}
if(bingo_add_new_entry(&bingo_bank[board], bingo_drawn_numbers[ind]))
{
p2_answer = bingo_board_compute_answer(&bingo_bank[board]);
bingo_bank[board].bingo_status = true;
++completed_boards;
}
#ifdef DEBUG
print_bingo_board(&bingo_bank[board]);
printf("Number of completed boards: %d\n", completed_boards);
#endif
}
if(completed_boards >= bingo_board_count)
{
break;
}
}
printf("Answer for part 2: %d\n", p2_answer);
return 0;
}
// returns
bool bingo_add_new_entry(board_t* board, uint8_t num)
{
for(int ind = 0; ind < 5; ind++)
{
for(int jind = 0; jind < 5; jind++)
{
if(board->matrix[ind][jind] == num)
{
board->output |= (1 << (ind * 5 + jind));
board->most_recently_drawn = num;
return bingo_board_win_check(board);
}
}
}
return false;
}
bool bingo_board_win_check(const board_t* board)
{
for(int wc = 0; wc < 10; wc++)
{
// found a winner check
if((board->output & win_conditions[wc]) == win_conditions[wc])
{
return true;
}
}
return false;
}
int bingo_board_compute_answer(const board_t* board)
{
int result = 0;
for(int ind = 0; ind < 5; ind++)
{
for(int jind = 0; jind < 5; jind++)
{
if(!(board->output & (1 << ((ind * 5) + jind))))
{
result += board->matrix[ind][jind];
}
}
}
result *= board->most_recently_drawn;
return result;
}
void print_bingo_board(const board_t* board)
{
printf("\n");
for(int ind = 0; ind < 5; ind++)
{
for(int jind = 0; jind < 5; jind++)
{
if(board->output & (1 << ((ind * 5) + jind)))
{
printf(RED "%2d " RESET, board->matrix[ind][jind]);
}
else
{
printf("%2d ", board->matrix[ind][jind]);
}
}
printf("\r\n");
}
}