aocpp/2022/02.cpp

144 lines
2.6 KiB
C++
Raw Normal View History

2023-01-25 13:48:54 -08:00
#include <algorithm>
#include <cstdint>
#include <iostream>
#include <numeric>
#include <sstream>
#include <stdexcept>
#include <string>
#include <tuple>
#include <vector>
#include <doctest.h>
#include <aocpp/Startup.hpp>
namespace {
enum class ABC {
A, B, C
};
enum class XYZ {
X, Y, Z
};
auto xyzScore(XYZ xyz) -> std::int64_t
{
switch (xyz) {
case XYZ::X: return 1;
case XYZ::Y: return 2;
case XYZ::Z: return 3;
}
}
auto outcome(ABC abc, XYZ xyz) -> std::int64_t
{
switch (abc) {
case ABC::A:
switch (xyz) {
case XYZ::X: return 3;
case XYZ::Y: return 6;
case XYZ::Z: return 0;
}
case ABC::B:
switch (xyz) {
case XYZ::X: return 0;
case XYZ::Y: return 3;
case XYZ::Z: return 6;
}
case ABC::C:
switch (xyz) {
case XYZ::X: return 6;
case XYZ::Y: return 0;
case XYZ::Z: return 3;
}
}
}
auto DesiredOutcome(XYZ xyz) -> std::int64_t
{
switch (xyz) {
case XYZ::X: return 0;
case XYZ::Y: return 3;
case XYZ::Z: return 6;
}
}
auto Pick(ABC abc, XYZ xyz) -> XYZ
{
for (auto result : {XYZ::X, XYZ::Y, XYZ::Z}) {
if (outcome(abc, result) == DesiredOutcome(xyz)) {
return result;
}
}
throw std::runtime_error{"Pick couldn't find result"};
}
using Input = std::vector<std::pair<ABC, XYZ>>;
auto Parse(std::istream & in) -> Input
{
Input result;
std::string abc, xyz;
while (in >> abc >> xyz) {
result.emplace_back(
abc == "A" ? ABC::A :
abc == "B" ? ABC::B :
ABC::C,
xyz == "X" ? XYZ::X :
xyz == "Y" ? XYZ::Y :
XYZ::Z
);
}
return result;
}
auto Part1(Input const& input) -> std::int64_t
{
return std::transform_reduce(
input.begin(), input.end(),
std::int64_t{0},
std::plus(),
[](auto x) {
auto [abc, xyz] = x;
return outcome(abc, xyz) + xyzScore(xyz);
});
}
auto Part2(Input const& input) -> std::int64_t
{
return std::transform_reduce(
input.begin(), input.end(),
std::int64_t{0},
std::plus(),
[](auto x) {
auto [abc, xyz] = x;
xyz = Pick(abc, xyz);
return outcome(abc, xyz) + xyzScore(xyz);
});
}
} // namespace
TEST_SUITE("2022-02 examples") {
TEST_CASE("example") {
std::istringstream in {
R"(A Y
B X
C Z
)"
};
auto const input = Parse(in);
CHECK(Part1(input) == 15);
CHECK(Part2(input) == 12);
}
}
auto main(int argc, char** argv) -> int {
auto const input {Parse(*aocpp::Startup(argc, argv))} ;
std::cout << "Part 1: " << Part1(input) << std::endl;
std::cout << "Part 2: " << Part2(input) << std::endl;
}