2022-25
This commit is contained in:
parent
68de78a585
commit
978a8ad39d
110
2022/25.cpp
Normal file
110
2022/25.cpp
Normal file
|
@ -0,0 +1,110 @@
|
|||
#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/Startup.hpp>
|
||||
|
||||
namespace {
|
||||
|
||||
//
|
||||
template <typename T>
|
||||
auto DivMod(T dividend, T divisor) -> std::pair<T, T>
|
||||
{
|
||||
auto const quotient = dividend / divisor;
|
||||
auto const remainder = dividend % divisor;
|
||||
if ((remainder >= 0) == (divisor >= 0)) {
|
||||
return {quotient, remainder};
|
||||
} else {
|
||||
return {quotient - 1, remainder + divisor};
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
{
|
||||
using It = std::istream_iterator<std::string>;
|
||||
return FromInt(std::transform_reduce(It(in), It(), 0, 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) == "=-");
|
||||
}
|
||||
|
||||
TEST_CASE("DivMod behavior") {
|
||||
CHECK(DivMod<int>(2,5) == std::make_pair(0,2));
|
||||
CHECK(DivMod<int>(-2,5) == std::make_pair(-1,3));
|
||||
CHECK(DivMod<int>(2,-5) == std::make_pair(-1,-3));
|
||||
CHECK(DivMod<int>(-2,-5) == std::make_pair(0,-2));
|
||||
}
|
||||
}
|
||||
|
||||
auto main(int argc, char** argv) -> int
|
||||
{
|
||||
std::cout << "Part 1: " << Solve(*aocpp::Startup(argc, argv)) << std::endl;
|
||||
}
|
|
@ -6,3 +6,6 @@ target_link_libraries(2022_03 aocpp)
|
|||
|
||||
add_executable(2022_04 04.cpp)
|
||||
target_link_libraries(2022_04 aocpp)
|
||||
|
||||
add_executable(2022_25 25.cpp)
|
||||
target_link_libraries(2022_25 aocpp)
|
||||
|
|
Loading…
Reference in New Issue
Block a user