diff --git a/2022/11.cpp b/2022/11.cpp new file mode 100644 index 0000000..5d30bee --- /dev/null +++ b/2022/11.cpp @@ -0,0 +1,152 @@ +#include +#include +#include +#include +#include +#include +#include + +#include + +#include + +namespace { + +struct Monkey { + std::vector items; + std::int64_t divisor; + std::size_t true_ix, false_ix; + std::optional rhs; + char op; +}; + +auto Parse(std::istream & in) -> std::vector +{ + std::string word; + std::vector monkies; + + while (in >> word) { + monkies.emplace_back(); + Monkey & m = monkies.back(); + + in >> word >> word >> word; // 0: Starting items: + + for (;;) { + std::int64_t elt; + in >> elt; + m.items.push_back(elt); + + char c; + in >> c; + if (c != ',') break; + } + + in >> word >> word >> word >> word; // Operation: new = old + + in >> m.op >> word; + if (word != "old") m.rhs = std::stoll(word); + + in >> word >> word >> word >> m.divisor; + in >> word >> word >> word >> word >> word >> m.true_ix + >> word >> word >> word >> word >> word >> m.false_ix; + } + + return monkies; +} + +auto Solve(std::vector const& input, std::size_t const rounds, std::optional const modulus) -> std::int64_t +{ + std::vector throws(input.size()); + for (std::size_t i = 0; i < input.size(); ++i) { + for (auto item : input[i].items) { + auto cursor = i; + for (auto n = rounds; n > 0;) { + throws[cursor]++; + auto const& m = input[cursor]; + + auto const y = m.rhs.value_or(item); + switch (m.op) { + case '+': item += y; break; + case '*': item *= y; break; + default: throw std::runtime_error{"bad input"}; + } + if (modulus.has_value()) { + item %= *modulus; + } else { + item /= 3; + } + + auto const next = (item % m.divisor == 0) ? m.true_ix : m.false_ix; + if (next < cursor) n--; + cursor = next; + } + } + } + + // Compute top 2 elements of the vector + std::partial_sort(throws.begin(), throws.begin()+2, throws.end(), std::greater()); + + return throws[0] * throws[1]; +} + +auto Part1(std::vector const& input) -> std::int64_t +{ + return Solve(input, 20, {}); +} + +auto Part2(std::vector const& input) -> std::int64_t +{ + auto const modulus = + std::transform_reduce( + input.cbegin(), input.cend(), + std::int64_t{1}, std::lcm, + [](Monkey const& m) { return m.divisor; }); + return Solve(input, 10'000, modulus); +} + +} // namespace + +TEST_SUITE("2022-11 examples") { + TEST_CASE("example") { + std::istringstream in { +R"(Monkey 0: + Starting items: 79, 98 + Operation: new = old * 19 + Test: divisible by 23 + If true: throw to monkey 2 + If false: throw to monkey 3 + +Monkey 1: + Starting items: 54, 65, 75, 74 + Operation: new = old + 6 + Test: divisible by 19 + If true: throw to monkey 2 + If false: throw to monkey 0 + +Monkey 2: + Starting items: 79, 60, 97 + Operation: new = old * old + Test: divisible by 13 + If true: throw to monkey 1 + If false: throw to monkey 3 + +Monkey 3: + Starting items: 74 + Operation: new = old + 3 + Test: divisible by 17 + If true: throw to monkey 0 + If false: throw to monkey 1 +)" + }; + auto const input = Parse(in); + CHECK(Part1(input) == 10605); + CHECK(Part2(input) == 2713310158); + } +} + +auto main(int argc, char** argv) -> int +{ + auto const input = Parse(*aocpp::Startup(argc, argv)); + std::cout << "Part 1: " << Part1(input) << std::endl; + std::cout << "Part 2: " << Part2(input) << std::endl; +} diff --git a/2022/CMakeLists.txt b/2022/CMakeLists.txt index ec51db3..db33860 100644 --- a/2022/CMakeLists.txt +++ b/2022/CMakeLists.txt @@ -19,6 +19,9 @@ target_link_libraries(2022_09 aocpp) add_executable(2022_10 10.cpp) target_link_libraries(2022_10 aocpp) +add_executable(2022_11 11.cpp) +target_link_libraries(2022_11 aocpp) + add_executable(2022_12 12.cpp) target_link_libraries(2022_12 aocpp)