#include #include #include #include #include #include #include #include #include #include #include #include #include #include namespace { namespace qi = boost::spirit::qi; namespace phx = boost::phoenix; namespace ascii = boost::spirit::ascii; struct Game { unsigned long long game_id; std::vector>> rounds; }; struct Grammar : public qi::grammar(), ascii::space_type> { qi::rule game; qi::rule(), ascii::space_type> games; qi::rule(), ascii::space_type> entry; Grammar() : base_type{games} { using namespace qi::labels; games = *game; game = "Game" >> qi::ulong_long [ phx::bind(&Game::game_id, _val) = _1] >> ":" >> (entry % "," % ";") [ phx::bind(&Game::rounds, _val) = _1]; entry = qi::ulong_long >> qi::lexeme [ qi::as_string[+qi::alpha] ]; } }; auto Part1(std::vector const& input) -> unsigned long long { static auto const limits = std::unordered_map{ {"red", 12}, {"green", 13}, {"blue", 14}, }; unsigned long long result = 0; for (auto const& game : input) { auto const good = std::all_of(game.rounds.begin(), game.rounds.end(), [](auto const& round) { return std::all_of(round.begin(), round.end(), [](auto const& entry) { auto const limit = limits.find(std::get<1>(entry)); return limit != limits.end() && limit->second >= std::get<0>(entry); }); }); if (good) { result += game.game_id; } } return result; } auto Part2(std::vector const& input) -> unsigned long long { unsigned long long result = 0; for (auto const& game : input) { std::unordered_map maxes; for (auto const& round : game.rounds) { for (auto const& [count, color] : round) { auto& entry = maxes[color]; entry = std::max(entry, count); } } result += std::transform_reduce( maxes.begin(), maxes.end(), 1ULL, std::multiplies{}, [](auto& kv) { return kv.second; }); } return result; } } // namespace TEST_SUITE("2023-02 examples") { TEST_CASE("example") { std::istringstream in { R"(Game 1: 3 blue, 4 red; 1 red, 2 green, 6 blue; 2 green Game 2: 1 blue, 2 green; 3 green, 4 blue, 1 red; 1 green, 1 blue Game 3: 8 green, 6 blue, 20 red; 5 blue, 4 red, 13 green; 5 green, 1 red Game 4: 1 green, 3 red, 6 blue; 3 green, 6 red; 3 green, 15 blue, 14 red Game 5: 6 red, 1 blue, 3 green; 2 blue, 1 red, 2 green )" }; auto const input = aocpp::ParseGrammar_(Grammar{}, in); CHECK(Part1(input) == 8); CHECK(Part2(input) == 2'286); } } auto Main(std::istream & in, std::ostream & out) -> void { auto const input = aocpp::ParseGrammar_(Grammar{}, in); out << "Part 1: " << Part1(input) << std::endl; out << "Part 2: " << Part2(input) << std::endl; }