aocpp/2020/02.cpp
2023-01-31 09:15:25 -08:00

72 lines
1.6 KiB
C++

#include <algorithm>
#include <cstdint>
#include <iostream>
#include <tuple>
#include <cstdio>
#include <cstdlib>
#include <doctest.h>
#include <aocpp/Startup.hpp>
namespace {
using Entry = std::tuple<std::size_t, std::size_t, char, std::string>;
auto Parse(std::string const& str) -> Entry
{
std::size_t lo, hi, n;
char letter;
auto res = std::sscanf(str.c_str(), "%zu-%zu %c: %zn", &lo, &hi, &letter, &n);
if (res != 3) { throw std::runtime_error{"bad input"}; }
return {lo, hi, letter, str.substr(n)};
}
auto Part1(Entry const& entry) -> bool {
auto const& [lo, hi, letter, text] = entry;
auto n = std::count(text.begin(), text.end(), letter);
return lo <= n && n <= hi;
}
auto Part2(Entry const& entry) -> bool
{
auto const& [lo, hi, letter, text] = entry;
return (text.at(lo-1) == letter) != (text.at(hi-1) == letter);
}
} // namespace
TEST_SUITE("documented examples") {
TEST_CASE("parser") {
REQUIRE(Parse("1-3 z: example") == Entry{1,3,'z',"example"});
}
TEST_CASE("part 1") {
REQUIRE( Part1(Parse("1-3 a: abcde")));
REQUIRE(!Part1(Parse("1-3 b: cdefg")));
REQUIRE( Part1(Parse("2-9 c: ccccccccc")));
}
TEST_CASE("part 2") {
REQUIRE( Part2(Parse("1-3 a: abcde")));
REQUIRE(!Part2(Parse("1-3 b: cdefg")));
REQUIRE(!Part2(Parse("2-9 c: ccccccccc")));
}
}
auto Main(std::istream & in, std::ostream & out) -> void
{
std::uint64_t part1{}, part2{};
std::string line;
while (std::getline(in, line)) {
auto entry = Parse(line);
if (Part1(entry)) part1++;
if (Part2(entry)) part2++;
}
out << "Part 1: " << part1 << std::endl;
out << "Part 2: " << part2 << std::endl;
}