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);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-01-31 08:58:42 -08:00
|
|
|
auto Main(std::istream & in) -> void
|
|
|
|
{
|
|
|
|
auto const input {Parse(in)} ;
|
2023-01-25 13:48:54 -08:00
|
|
|
std::cout << "Part 1: " << Part1(input) << std::endl;
|
|
|
|
std::cout << "Part 2: " << Part2(input) << std::endl;
|
|
|
|
}
|