#include #include #include #include #include #include #include #include namespace { using Entry = std::tuple; 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) -> 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++; } std::cout << "Part 1: " << part1 << std::endl; std::cout << "Part 2: " << part2 << std::endl; }