#include #include #include #include #include #include #include #include #include #include #include #include namespace { using Input = std::vector; /// @brief Parse the input stream as a newline-delimited list of lists of integers /// @param in input file parsed until EOF /// @return outer list of elves, inner lists of calories auto Parse(std::istream & in) -> Input { Input result; using It = std::istream_iterator; std::copy(in, {}, std::back_inserter(result)); return result; } auto Solve(Input const& input, std::size_t const rounds) -> std::int64_t { std::size_t const len = input.size(); std::vector fwds(len), bwds(len); std::iota(fwds.begin(), fwds.end()-1, 1); fwds.back() = 0; std::iota(bwds.begin()+1, bwds.end(), 0); bwds.front() = len-1; for (std::size_t r = 0; r < rounds; ++r) { for (std::size_t i = 0; i < len; ++i) { // Remove i from the ring auto next = fwds[i]; auto prev = bwds[i]; fwds[prev] = next; bwds[next] = prev; auto const steps = aocpp::Mod(input[i], len - 1); if (steps < len/2) { for (std::size_t s = 0; s < steps; ++s) { next = fwds[next]; } } else { for (std::size_t s = 0; s < len - 1 - steps; ++s) { next = bwds[next]; } } prev = bwds[next]; // insert i into the ring fwds[i] = next; bwds[i] = prev; fwds[prev] = i; bwds[next] = i; } } std::int64_t sum {0}; auto cursor = std::distance(input.begin(), std::find(input.begin(), input.end(), 0)); for (std::size_t r = 0; r < 3; ++r) { for (std::size_t s = 0; s < 1000; ++s) { cursor = fwds[cursor]; } sum += input[cursor]; } return sum; } auto Part1(Input const& input) -> std::int64_t { return Solve(input, 1); } auto Part2(Input input) -> std::int64_t { for (auto& x : input) { x *= 811589153; } return Solve(input, 10); } } // namespace TEST_SUITE("2022-20 examples") { TEST_CASE("example") { std::istringstream in { "1\n" "2\n" "-3\n" "3\n" "-2\n" "0\n" "4\n"}; auto input = Parse(in); CHECK(3 == Part1(input)); CHECK(1623178306 == Part2(input)); } } auto main(int argc, char** argv) -> int { auto input = Parse(*aocpp::Startup(argc, argv)); std::cout << "Part 1: " << Part1(input) << std::endl; std::cout << "Part 2: " << Part2(input) << std::endl; }