169 lines
4.1 KiB
C++
169 lines
4.1 KiB
C++
|
#include <array>
|
||
|
#include <fstream>
|
||
|
#include <iostream>
|
||
|
#include <sstream>
|
||
|
#include <vector>
|
||
|
|
||
|
class Bingo {
|
||
|
public:
|
||
|
Bingo() = default;
|
||
|
~Bingo() = default;
|
||
|
|
||
|
void addNumberToCard(int number) {
|
||
|
card[numbers / 5][numbers % 5] = {number, false};
|
||
|
numbers += 1;
|
||
|
}
|
||
|
|
||
|
void checkNumber(int number) {
|
||
|
if(hasWon()) {
|
||
|
invalidate();
|
||
|
return;
|
||
|
}
|
||
|
for(int i = 0; i < 5; i++) {
|
||
|
for(int j = 0; j < 5; j++) {
|
||
|
if(card[i][j].first == number) {
|
||
|
card[i][j].second = true;
|
||
|
checkWin(number);
|
||
|
return;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
bool hasWon() {
|
||
|
return won;
|
||
|
}
|
||
|
|
||
|
int getWinningScore() {
|
||
|
return winning_score;
|
||
|
}
|
||
|
|
||
|
void printSelf() {
|
||
|
std::cout << std::endl;
|
||
|
for(int i = 0; i < 5; i++) {
|
||
|
for(int j = 0; j < 5; j++) {
|
||
|
if(card[i][j].second) {
|
||
|
std::cout << "*";
|
||
|
}
|
||
|
std::cout << card[i][j].first << " ";
|
||
|
}
|
||
|
std::cout << std::endl;
|
||
|
}
|
||
|
std::cout << std::endl;
|
||
|
}
|
||
|
|
||
|
bool isValid() {
|
||
|
return valid;
|
||
|
}
|
||
|
|
||
|
private:
|
||
|
void checkWin(int multiplier) {
|
||
|
for(int i = 0; i < 5; i++) {
|
||
|
int horizontal = 0;
|
||
|
int vertical = 0;
|
||
|
for(int j = 0; j < 5; j++) {
|
||
|
if(card[i][j].second) {
|
||
|
horizontal += 1;
|
||
|
}
|
||
|
if(card[j][i].second) {
|
||
|
vertical += 1;
|
||
|
}
|
||
|
}
|
||
|
if(horizontal == 5 || vertical == 5) {
|
||
|
won = true;
|
||
|
calculateScore(multiplier);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void calculateScore(int multiplier) {
|
||
|
int score = 0;
|
||
|
for(int i = 0; i < 5; i++) {
|
||
|
for(int j = 0; j < 5; j++) {
|
||
|
if(!card[i][j].second) {
|
||
|
score += card[i][j].first;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
winning_score = score * multiplier;
|
||
|
}
|
||
|
|
||
|
void invalidate() {
|
||
|
valid = false;
|
||
|
}
|
||
|
|
||
|
|
||
|
std::array<std::array<std::pair<int,bool>, 5>, 5> card;
|
||
|
int numbers = 0;
|
||
|
bool won = false;
|
||
|
int winning_score = -1;
|
||
|
bool valid = true;
|
||
|
};
|
||
|
|
||
|
std::pair<std::vector<int>, std::vector<Bingo>> getBingo(const std::string &file_name) {
|
||
|
std::pair<std::vector<int>, std::vector<Bingo>> result;
|
||
|
|
||
|
std::ifstream file(file_name);
|
||
|
int tmp{};
|
||
|
char tmp_char{};
|
||
|
std::string str;
|
||
|
std::getline(file, str);
|
||
|
std::stringstream ss(str);
|
||
|
while(ss >> tmp) {
|
||
|
result.first.push_back(tmp);
|
||
|
ss >> tmp_char;
|
||
|
}
|
||
|
while (std::getline(file, str)) {
|
||
|
if(str.empty()) {
|
||
|
result.second.emplace_back();
|
||
|
continue;
|
||
|
}
|
||
|
std::stringstream ss2(str);
|
||
|
for(int i = 0; i < 5; i++) {
|
||
|
ss2 >> tmp;
|
||
|
result.second.back().addNumberToCard(tmp);
|
||
|
}
|
||
|
}
|
||
|
return result;
|
||
|
}
|
||
|
|
||
|
int part1(const std::vector<int> &numbers, std::vector<Bingo> &bingo) {
|
||
|
for(auto &number : numbers) {
|
||
|
for(auto &card : bingo) {
|
||
|
card.checkNumber(number);
|
||
|
if(card.hasWon()) {
|
||
|
return card.getWinningScore();
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
int part2(const std::vector<int> &numbers, std::vector<Bingo> &bingo) {
|
||
|
int last_score = -1;
|
||
|
for(auto &number : numbers) {
|
||
|
for(auto &card : bingo) {
|
||
|
card.checkNumber(number);
|
||
|
if(card.hasWon() && card.isValid()) {
|
||
|
last_score = card.getWinningScore();
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
return last_score;
|
||
|
}
|
||
|
|
||
|
int main(int argc, char **argv) {
|
||
|
if (argc < 2) {
|
||
|
std::cerr << "You must provide input file!" << std::endl;
|
||
|
return 1;
|
||
|
}
|
||
|
auto input = getBingo(argv[1]);
|
||
|
auto &numbers = input.first;
|
||
|
auto &bingo = input.second;
|
||
|
std::cout << "The winning score of the first winning card is \033[91;1m"
|
||
|
<< part1(numbers, bingo) << "\033[0m." << std::endl;
|
||
|
std::cout << "The winning score of the last winning card is \033[91;1m"
|
||
|
<< part2(numbers, bingo) << "\033[0m." << std::endl;
|
||
|
return 0;
|
||
|
}
|