From 574b8c3ebc2deef52f9bf814b78c90da9d8d4d22 Mon Sep 17 00:00:00 2001 From: Eric Mertens Date: Sat, 2 Dec 2023 20:15:21 -0800 Subject: [PATCH] 2023-02 --- 2023/02.cpp | 118 ++++++++++++++++++++++++++++++++++++++++++++ 2023/CMakeLists.txt | 2 + CMakeLists.txt | 1 + 3 files changed, 121 insertions(+) create mode 100644 2023/02.cpp create mode 100644 2023/CMakeLists.txt diff --git a/2023/02.cpp b/2023/02.cpp new file mode 100644 index 0000000..74d383b --- /dev/null +++ b/2023/02.cpp @@ -0,0 +1,118 @@ +#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; +} diff --git a/2023/CMakeLists.txt b/2023/CMakeLists.txt new file mode 100644 index 0000000..9a646ac --- /dev/null +++ b/2023/CMakeLists.txt @@ -0,0 +1,2 @@ +add_executable(2023_02 02.cpp) +target_link_libraries(2023_02 aocpp Boost::headers) diff --git a/CMakeLists.txt b/CMakeLists.txt index a86abe5..94e5b4e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -33,3 +33,4 @@ add_subdirectory(2019) add_subdirectory(2020) add_subdirectory(2021) add_subdirectory(2022) +add_subdirectory(2023)