aocpp/2022/25.cpp
2023-01-31 08:59:09 -08:00

94 lines
2.0 KiB
C++

#include <cstdint> // int64_t
#include <functional> // plus
#include <iostream> // istream
#include <iterator> // istream_iterator
#include <numeric> // transform_reduce
#include <sstream> // istringstream
#include <string> // string
#include <tuple> // pair, make_pair
#include <doctest.h>
#include <aocpp/DivMod.hpp>
#include <aocpp/Startup.hpp>
namespace {
using aocpp::DivMod;
using It = std::istream_iterator<std::string>;
template <typename T>
auto FromInt(T x) -> std::string
{
std::string output;
char const digits[] {"=-012"};
while (x != 0) {
auto [x_, i] = DivMod<T>(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 <typename T>
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<std::int64_t>));
}
} // 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<int>("-") == -1);
CHECK(ToInt<int>("=") == -2);
CHECK(ToInt<int>("-=") == -7);
CHECK(ToInt<int>("=-") == -11);
CHECK(FromInt(-1) == "-");
CHECK(FromInt(-2) == "=");
CHECK(FromInt(-7) == "-=");
CHECK(FromInt(-11) == "=-");
}
}
auto Main(std::istream & in) -> void
{
std::cout << "Part 1: " << Solve(in) << std::endl;
}