#include #include #include #include #include #include #include #include #include #include namespace { /* \ n / nw +--+ ne / \ -+ +- \ / sw +--+ se / s \ */ struct Hex { std::int64_t q, r, s; }; constexpr Hex HEX_N { 0, -1, 1 }; constexpr Hex HEX_NE { 1, -1, 0 }; constexpr Hex HEX_SE { 1, 0, -1 }; constexpr Hex HEX_S { 0, 1, -1 }; constexpr Hex HEX_SW { -1, 1, 0 }; constexpr Hex HEX_NW { -1, 0, 1 }; auto operator+(Hex a, Hex b) -> Hex { return {a.q + b.q, a.r + b.r, a.s + b.s }; } auto operator+=(Hex & a, Hex b) -> Hex & { a.q += b.q; a.r += b.r; a.s += b.s; return a; } auto hex_distance(Hex hex) -> std::int64_t { return (std::abs(hex.q) + std::abs(hex.r) + std::abs(hex.s)) / 2; } auto Walk(std::string const& commands) -> std::pair { Hex here {}; std::int64_t part2 = 0; for (auto const& command : aocpp::SplitOn(commands, ",")) { here += "n" == command ? HEX_N : "ne" == command ? HEX_NE : "nw" == command ? HEX_NW : "s" == command ? HEX_S : "se" == command ? HEX_SE : "sw" == command ? HEX_SW : throw std::runtime_error{"bad input"}; part2 = std::max(part2, hex_distance(here)); } return {hex_distance(here), part2}; } } // namespace TEST_SUITE("2017-11 examples") { TEST_CASE("example 1") { auto [p1,p2] = Walk("ne,ne,ne"); CHECK(p1 == 3); CHECK(p2 == 3); } TEST_CASE("example 2") { auto [p1,p2] = Walk("ne,ne,sw,sw"); CHECK(p1 == 0); CHECK(p2 == 2); } TEST_CASE("example 3") { auto [p1,p2] = Walk("ne,ne,s,s"); CHECK(p1 == 2); CHECK(p2 == 2); } TEST_CASE("example 4") { auto [p1,p2] = Walk("se,sw,se,sw,sw"); CHECK(p1 == 3); CHECK(p2 == 3); } } auto main(int argc, char** argv) -> int { std::string line; std::getline(*aocpp::Startup(argc, argv), line); auto [part1, part2] = Walk(line); std::cout << "Part 1: " << part1 << std::endl; std::cout << "Part 2: " << part2 << std::endl; }