1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
|
#include <stdlib.h>
#include <stdio.h>
#include <err.h>
#include <stdbool.h>
#include "input.h"
#define INPUT "input/04.txt"
#define BOARD_COUNT 100
#define BOARD_SIZE 5
#define MAX_DRAW 500
typedef struct {
long board[BOARD_SIZE][BOARD_SIZE];
bool board_marks[BOARD_SIZE][BOARD_SIZE];
} t_board;
bool board_is_winning(t_board* board) {
for(int i = 0; i < BOARD_SIZE; i++) {
bool winning_i = true;
bool winning_j = true;
for(int j = 0; j < BOARD_SIZE; j++) {
winning_i &= board->board_marks[i][j];
winning_j &= board->board_marks[j][i];
}
if(winning_i || winning_j)
return true;
}
return false;
}
bool board_mark(t_board* board, long draw) {
for(int i = 0; i < BOARD_SIZE; i++) {
for(int j = 0; j < BOARD_SIZE; j++) {
if(board->board[i][j] == draw)
board->board_marks[i][j] = true;
}
}
return board_is_winning(board);
}
void board_init(t_board* board) {
for(int i = 0; i < BOARD_SIZE; i++) {
for(int j = 0; j < BOARD_SIZE; j++) {
board->board[i][j] = 0;
board->board_marks[i][j] = false;
}
}
}
void board_read(t_board* board_list, struct input_str* input) {
for(int i = 0; i < BOARD_COUNT; i++) {
board_init(&(board_list[i]));
// read each line of the board
for(int j = 0; j < BOARD_SIZE; j++) {
// + 2 is for first line and empty line at start of board
int line_index = i * (BOARD_SIZE + 1) + j + 2;
char* line = input->lines[line_index];
char* start = line;
char* end = NULL;
// read each int
for(int k = 0; k < BOARD_SIZE; k++) {
board_list[i].board[j][k] = strtol(start, &end, 0);
start = end;
}
}
}
}
size_t draw_read(long* draw_list, struct input_str* input) {
size_t i = 0;
char *start = input->lines[0];
char *end = start;
while(i < MAX_DRAW && *end != '\n') {
draw_list[i] = strtol(start, &end, 0);
start = end + 1;
i++;
}
if(i == MAX_DRAW && *end != '\n')
err(1, "draw list was truncated");
return i;
}
long board_unmarked_sum(t_board* board) {
long sum = 0;
for(int i = 0; i < BOARD_SIZE; i++) {
for(int j = 0; j < BOARD_SIZE; j++) {
if(!(board->board_marks)[i][j])
sum += (board->board)[i][j];
}
}
return sum;
}
void part1(struct input_str* input) {
t_board board_list[BOARD_COUNT];
long draw_list[MAX_DRAW];
board_read(board_list, input);
size_t draw_count = draw_read(draw_list, input);
// apply draw to each board until one is winning
for(size_t i = 0; i < draw_count; i++) {
for(size_t j = 0; j < BOARD_COUNT; j++) {
if(board_mark(&(board_list[j]), draw_list[i])) {
// winning board found, print score
long score = board_unmarked_sum(&(board_list[j]));
printf("%ld\n", draw_list[i] * score);
return;
}
}
}
err(1, "no winning board");
}
void part2(struct input_str* input) {
t_board board_list[BOARD_COUNT];
long draw_list[MAX_DRAW];
board_read(board_list, input);
size_t draw_count = draw_read(draw_list, input);
// apply draw to each board until one is winning
long last_score;
for(size_t i = 0; i < draw_count; i++) {
for(size_t j = 0; j < BOARD_COUNT; j++) {
// skip already winning boards
if(board_is_winning(&(board_list[j])))
continue;
if(board_mark(&(board_list[j]), draw_list[i])) {
// winning board found
last_score = draw_list[i] * board_unmarked_sum(&(board_list[j]));
}
}
}
// print last winning
printf("%ld\n", last_score);
}
int main() {
// read input
struct input_str input;
input_str_read(&input, INPUT);
// do stuff
part1(&input);
part2(&input);
// cleanup & exit
input_str_free(&input);
return 0;
}
|