#include #include #include #include #include #include #include #include #include namespace { template using Banks = std::array; auto Parse(std::istream & in) -> Banks<16> { Banks<16> result; for (auto & x : result) { if (!(in >> x)) { throw std::runtime_error{"bad input"}; } } return result; } template auto Redistribute(Banks & banks) { auto it = std::max_element(banks.begin(), banks.end()); auto val = *it; *it++ = 0; for (; val > 0; val--) { if (it == banks.end()) it = banks.begin(); (*it++)++; } } template auto CycleSearch(Banks & banks) -> std::pair { std::map, std::size_t> seen {{banks, 0}}; std::size_t n = 0; for(;;) { Redistribute(banks); n++; auto [it, success] = seen.try_emplace(banks, n); if (!success) { return {n, n - it->second}; } } } } // namespace TEST_SUITE("2017-06 examples") { TEST_CASE("example") { Banks<4> banks {0, 2, 7, 0}; SUBCASE("single step") { Redistribute(banks); REQUIRE(banks == Banks<4>{2, 4, 1, 2}); Redistribute(banks); REQUIRE(banks == Banks<4>{3, 1, 2, 3}); Redistribute(banks); REQUIRE(banks == Banks<4>{0, 2, 3, 4}); Redistribute(banks); REQUIRE(banks == Banks<4>{1, 3, 4, 1}); Redistribute(banks); REQUIRE(banks == Banks<4>{2, 4, 1, 2}); } SUBCASE("full example") { auto [p1,p2] = CycleSearch(banks); CHECK(p1 == 5); CHECK(p2 == 4); } } } auto Main(std::istream & in) -> void { auto input {Parse(in)}; auto const answer = CycleSearch(input); std::cout << "Part 1: " << answer.first << std::endl; std::cout << "Part 2: " << answer.second << std::endl; }