#include namespace views = std::views; namespace ranges = std::ranges; using set = std::pair; auto parse_input(std::istream& is) { const std::string input = { std::istreambuf_iterator(is), std::istreambuf_iterator() }; auto const lines = input | views::split(std::string_view{"\n\n"}) | views::filter([](auto&& line) { return not line.empty(); }) | ranges::to>(); auto const sets = lines[0] | views::split('\n') | views::filter([](auto&& line) { return not line.empty(); }) | views::transform([](auto&& element) -> set { auto const l = element | views::split('-') | ranges::to>(); return set{std::stoull(l[0]), std::stoull(l[1])}; }) | ranges::to>(); auto const numbers = lines[1] | views::split('\n') | views::filter([](auto&& line) { return not line.empty(); }) | views::transform([](auto&& elem) -> uint64_t { return std::stoull(elem | ranges::to()); }) | ranges::to(); // Parse input return std::make_tuple(sets, numbers); } void part1(auto const& input) { // Write first part solution here auto const& [sets, numbers] = input; uint64_t answer = 0; for (auto const n : numbers) { answer += ranges::count_if(sets, [n](auto const& set) { return set.first <= n and n <= set.second; }) > 0; } std::println("{}", answer); } std::vector merge_sets(std::vector sets) { ranges::sort(sets); std::vector merged_sets = {sets[0]}; merged_sets.reserve(sets.size()); for (auto const& next : sets) { auto& last = merged_sets.back(); if (last.second + 1 < next.first) { // gap: [(1, 5), (7, 12)] merged_sets.push_back(next); } else { // no gap: [(1, 5), (4, 8)] last.second = std::max(last.second, next.second); } } return merged_sets; } void part2(auto const& input) { // Write second part solution here auto const& [sets, numbers] = input; auto const merged_sets = merge_sets(sets); uint64_t answer = 0; for (auto const set : merged_sets) { answer += set.second - set.first + 1; } std::println("{}", answer); } int main() { auto const input = parse_input(std::cin); part1(input); part2(input); return 0; }