#include #include #include #include #include #include #include #include #include #include using namespace aocpp; namespace { using Dir = Coord(*)(Coord); auto ToDir(char c) -> Dir { switch (c) { case 'L': return Left; case 'R': return Right; case 'D': return Down; case 'U': return Up; default: throw std::runtime_error{"bad input"}; } } /// @brief Return the sign of the number /// @param x number /// @return -1, 0, or 1 matching the sign of the input auto Sign(std::int64_t x) -> std::int64_t { return (x>0) - (x<0); } auto Solve(std::istream & in) -> std::pair { std::size_t constexpr knotn {10}; Coord knots[knotn] {}; std::set p1{knots[1]}, p2{knots[9]}; char d; long n; while (in >> d >> n) { auto const dir = ToDir(d); while (n--) { knots[0] = dir(knots[0]); std::size_t k; for (k = 1; k < knotn; ++k) { auto const delta {knots[k-1] - knots[k]}; if (NormInf(delta) <= 1) { break; } knots[k] += {Sign(delta.x), Sign(delta.y)}; } if (k > 1) { p1.insert(knots[1]); if (k > 9) { p2.insert(knots[9]); } } } } return {p1.size(), p2.size()}; } } // namespace TEST_SUITE("2022-09 examples") { TEST_CASE("example") { std::istringstream in { "R 5\n" "U 8\n" "L 8\n" "D 3\n" "R 17\n" "D 10\n" "L 25\n" "U 20\n"}; auto [p1,p2] = Solve(in); CHECK(p1 == 88); CHECK(p2 == 36); } } auto main(int argc, char** argv) -> int { auto [p1,p2] = Solve(*aocpp::Startup(argc, argv)); std::cout << "Part 1: " << p1 << std::endl; std::cout << "Part 2: " << p2 << std::endl; }