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
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");
|
|
}
|
|
}
|