diff --git a/2023/04.cpp b/2023/04.cpp new file mode 100644 index 0000000..e62afc4 --- /dev/null +++ b/2023/04.cpp @@ -0,0 +1,110 @@ +#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 Card +{ + unsigned long long id; + std::vector mine; + std::vector winners; +}; + +struct Grammar : public qi::grammar(), ascii::space_type> { + qi::rule card; + qi::rule(), ascii::space_type> cards; + + Grammar() : base_type{cards} { + using namespace qi::labels; + cards = *card; + card = + "Card" >> qi::ulong_long [ phx::bind(&Card::id, _val) = _1] >> ":" >> + (*qi::ulong_long) [ phx::bind(&Card::mine, _val) = _1] >> "|" >> + (*qi::ulong_long) [ phx::bind(&Card::winners, _val) = _1]; + } +}; + +auto CountWins(std::vector& cards) -> std::vector +{ + std::vector result; + result.reserve(cards.size()); + + for (auto& card : cards) + { + std::vector xs; + std::sort(card.mine.begin(), card.mine.end()); + std::sort(card.winners.begin(), card.winners.end()); + std::set_intersection(card.mine.begin(), card.mine.end(), card.winners.begin(), card.winners.end(), std::back_inserter(xs)); + result.push_back(xs.size()); + } + + return result; +} + +auto Part1(std::vector const& wins) -> std::uint64_t +{ + std::uint64_t result = 0; + for (auto const win : wins) + { + if (win > 0) + { + result += std::uint64_t{1} << (win - 1); + } + } + return result; +} + +auto Part2(std::vector const& wins) -> std::size_t +{ + std::vector psums(wins); + psums.push_back(0); + for (std::size_t i = wins.size(); i --> 0;) + { + psums[i] = 1 + 2 * psums[i+1] - psums[1 + i + psums[i]]; + } + return psums.front(); +} + +} // namespace + +TEST_SUITE("2023-04 examples") { + TEST_CASE("example") { + std::istringstream in { +R"(Card 1: 41 48 83 86 17 | 83 86 6 31 17 9 48 53 +Card 2: 13 32 20 16 61 | 61 30 68 82 17 32 24 19 +Card 3: 1 21 53 59 44 | 69 82 63 72 16 21 14 1 +Card 4: 41 92 73 84 69 | 59 84 76 51 58 5 54 83 +Card 5: 87 83 26 28 32 | 88 30 70 12 93 22 82 36 +Card 6: 31 18 13 56 72 | 74 77 10 23 35 67 36 11 +)" + }; + auto input = aocpp::ParseGrammar_(Grammar{}, in); + auto const wins = CountWins(input); + CHECK(Part1(wins) == 13); + CHECK(Part2(wins) == 30); + } +} + +auto Main(std::istream & in, std::ostream & out) -> void +{ + auto input = aocpp::ParseGrammar_(Grammar{}, in); + auto const wins = CountWins(input); + out << "Part 1: " << Part1(wins) << std::endl; + out << "Part 2: " << Part2(wins) << std::endl; +} diff --git a/2023/CMakeLists.txt b/2023/CMakeLists.txt index 9a646ac..bff6a05 100644 --- a/2023/CMakeLists.txt +++ b/2023/CMakeLists.txt @@ -1,2 +1,5 @@ add_executable(2023_02 02.cpp) target_link_libraries(2023_02 aocpp Boost::headers) + +add_executable(2023_04 04.cpp) +target_link_libraries(2023_04 aocpp Boost::headers)