#include // int64_t #include // plus #include // istream #include // istream_iterator #include // transform_reduce #include // istringstream #include // string #include // pair, make_pair #include #include namespace { using It = std::istream_iterator; // template auto DivMod(T dividend, T divisor) -> std::pair { auto const quotient = dividend / divisor; auto const remainder = dividend % divisor; if (remainder == 0 || (remainder > 0) == (divisor > 0)) { return {quotient, remainder}; } else { return {quotient - 1, remainder + divisor}; } } template auto FromInt(T x) -> std::string { std::string output; char const digits[] {"=-012"}; while (x != 0) { auto [x_, i] = DivMod(x + 2, 5); // plain % and / are insufficient for negatives x = x_; output.push_back(digits[i]); } std::reverse(output.begin(), output.end()); return output; } template auto ToInt(std::string const& str) -> T { T acc {0}; for (char c : str) { acc *= 5; switch (c) { case '2': acc += 2; break; case '1': acc += 1; break; case '0': break; case '-': acc -= 1; break; case '=': acc -= 2; break; } } return acc; } auto Solve(std::istream & in) -> std::string { return FromInt(std::transform_reduce(It{in}, It{}, std::int64_t{}, std::plus(), ToInt)); } } // namespace TEST_SUITE("2022-25 examples") { TEST_CASE("example") { std::istringstream in { "1=-0-2\n" "12111\n" "2=0=\n" "21\n" "2=01\n" "111\n" "20012\n" "112\n" "1=-1=\n" "1-12\n" "12\n" "1=\n" "122\n" }; CHECK(Solve(in) == "2=-1=0"); } // The example input doesn't test out any negative numbers TEST_CASE("Negative numbers") { CHECK(ToInt("-") == -1); CHECK(ToInt("=") == -2); CHECK(ToInt("-=") == -7); CHECK(ToInt("=-") == -11); CHECK(FromInt(-1) == "-"); CHECK(FromInt(-2) == "="); CHECK(FromInt(-7) == "-="); CHECK(FromInt(-11) == "=-"); } TEST_CASE("DivMod behavior") { CHECK(DivMod(2,5) == std::make_pair(0,2)); CHECK(DivMod(-2,5) == std::make_pair(-1,3)); CHECK(DivMod(2,-5) == std::make_pair(-1,-3)); CHECK(DivMod(-2,-5) == std::make_pair(0,-2)); CHECK(DivMod(-5,-5) == std::make_pair(1,0)); CHECK(DivMod(-5,5) == std::make_pair(-1,0)); CHECK(DivMod(5,-5) == std::make_pair(-1,0)); CHECK(DivMod(-5,-5) == std::make_pair(1,0)); } } auto main(int argc, char** argv) -> int { std::cout << "Part 1: " << Solve(*aocpp::Startup(argc, argv)) << std::endl; }