advent_of_code_2021/04/main.cpp
2021-12-05 09:52:11 +01:00

169 lines
4.2 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;
}