// // Created by Matthew Gretton-Dann on 04/12/2021. // #include #include #include #include #include #include #include #include using Number = unsigned long; // NOLINT(google-runtime-int) using NumberVector = std::vector; auto parse_number_list(std::string const& s) -> NumberVector { std::size_t idx{0}; NumberVector result; while (idx < s.size()) { std::size_t end{0}; result.push_back(std::stoul(s.substr(idx), &end)); idx += end; while (idx < s.size() && s[idx] == ',') { ++idx; } } return result; } struct BingoCard { public: explicit BingoCard(std::array const& card) { unsigned row{0}; for (auto const& s : card) { std::size_t idx{0}; for (unsigned col{0}; col < 5; ++col) { while (s.at(idx) == ' ') { ++idx; } std::size_t end{0}; numbers_.at(row + col) = {std::stoul(s.substr(idx), &end), false}; idx += end; } assert(idx == s.size()); row += 5; } } void mark(unsigned num) { for (auto it{// NOLINT(llvm-qualified-auto,readability-qualified-auto) find_num(numbers_.begin(), numbers_.end(), num)}; it != numbers_.end(); it = find_num(++it, numbers_.end(), num)) { it->second = true; } } [[nodiscard]] auto bingo() const -> bool { for (unsigned row{0}; row < 25; row += 5) { if (std::all_of(numbers_.begin() + row, numbers_.begin() + row + 5, [](auto const& n) { return n.second; })) { return true; } } for (unsigned col{0}; col < 5; ++col) { unsigned marked_count{0}; for (unsigned row{col}; row < 25; row += 5) { if (numbers_.at(row).second) { ++marked_count; } } if (marked_count == 5) { return true; } } return false; } [[nodiscard]] auto score() const -> Number { return std::accumulate(numbers_.begin(), numbers_.end(), Number{0}, [](Number a, auto const& n) { return a + (n.second ? 0 : n.first); }); } auto print(std::ostream& os) const -> std::ostream& { for (unsigned i = 0; i < 25; ++i) { os << std::setw(3) << numbers_.at(i).first << (numbers_.at(i).second ? "!" : " ") << ((i % 5 == 4) ? '\n' : ' '); } return os; } private: using NumberPair = std::pair; using NumberArray = std::array; static auto find_num(NumberArray::iterator begin, NumberArray::iterator end, Number num) -> NumberArray ::iterator { return std::find_if(begin, end, [num](auto const& n) { return n.first == num; }); } NumberArray numbers_; }; auto main() -> int { std::string line; if (!getline(std::cin, line)) { std::cerr << "Unable to read random numbers.\n"; return 1; } NumberVector random_numbers{parse_number_list(line)}; std::vector cards; while (std::getline(std::cin, line)) { assert(line.empty()); std::array lines; for (unsigned row{0}; row < 5; ++row) { std::getline(std::cin, lines.at(row)); } cards.emplace_back(lines); } for (auto num : random_numbers) { std::cout << num << ", "; for (auto& card : cards) { card.mark(num); if (card.bingo()) { auto score{card.score()}; std::cout << "\nBINGO " << score << " * " << num << " = " << score * num << '\n'; card.print(std::cout); std::cout << "Num cards: " << cards.size() << '\n'; return 0; } } } std::cerr << "No bingo!\n"; return 1; }