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

106 lines
2.5 KiB
C++

#include <algorithm>
#include <cstdint>
#include <iostream>
#include <numeric>
#include <sstream>
#include <stdexcept>
#include <string>
#include <tuple>
#include <vector>
#include <string_view>
#include <boost/range/irange.hpp>
#include <doctest.h>
#include <aocpp/Startup.hpp>
namespace {
auto Parse(std::istream & in) -> std::vector<std::string>
{
std::vector<std::string> result;
std::string line;
while (std::getline(in, line)) {
result.emplace_back(std::move(line));
}
return result;
}
auto Priority(char const c) -> std::int64_t
{
return c < 'a' ? c-'A'+27 : c-'a'+1;
}
auto Intersect(
std::string::const_iterator start1, std::string::const_iterator end1,
std::string::const_iterator start2, std::string::const_iterator end2
) -> std::string
{
std::string common;
std::set_intersection(
start1, end1,
start2, end2,
std::back_inserter(common));
return common;
}
auto Part1(std::vector<std::string> & input) -> std::int64_t
{
return std::transform_reduce(
input.begin(), input.end(),
std::int64_t{0}, std::plus(), // sum
[](auto & line) {
auto const mid = line.begin() + line.size() / 2;
std::sort(line.begin(), mid);
std::sort(mid, line.end());
auto const common = Intersect(line.begin(), mid, mid, line.end());
return Priority(common.at(0));
});
}
auto Part2(std::vector<std::string> & input) -> std::int64_t
{
for (auto & line : input) {
std::sort(line.begin(), line.end());
}
auto const range = boost::irange<std::size_t>(0, input.size(), 3);
return std::transform_reduce(
range.begin(), range.end(),
std::int64_t{0}, std::plus(), // sum
[&input](auto const i) {
auto const input01 = Intersect(
input[i ].begin(), input[i ].end(),
input[i+1].begin(), input[i+1].end());
auto const input012 = Intersect(
input01 .begin(), input01 .end(),
input[i+2].begin(), input[i+2].end());
return Priority(input012.at(0));
});
}
} // namespace
TEST_SUITE("2022-03 examples") {
TEST_CASE("example") {
std::istringstream in {
"vJrwpWtwJgWrhcsFMMfFFhFp\n"
"jqHRNqRjqzjGDLGLrsFMfFZSrLrFZsSL\n"
"PmmdzqPrVvPwwTWBwg\n"
"wMqvLMZHhHMvwLHjbvcjnnSBnvTQFn\n"
"ttgJtRGJQctTZtZT\n"
"CrZsJsPPZsGzwwsLwLmpwMDw\n"};
auto input = Parse(in);
CHECK(Part1(input) == 157);
CHECK(Part2(input) == 70);
}
}
auto Main(std::istream & in, std::ostream & out) -> void
{
auto input {Parse(in)};
out << "Part 1: " << Part1(input) << std::endl;
out << "Part 2: " << Part2(input) << std::endl;
}