summaryrefslogtreecommitdiffstats
path: root/day05/solution.cpp
blob: fa4ff87339c989ed85a20197f6a3efeb1e6fbc10 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
#include <bits/stdc++.h>

namespace views = std::views;
namespace ranges = std::ranges;
using set = std::pair<uint64_t, uint64_t>;

auto parse_input(std::istream& is) {
    const std::string input = {
        std::istreambuf_iterator<char>(is),
        std::istreambuf_iterator<char>()
    };

    auto const lines = input
        | views::split(std::string_view{"\n\n"})
        | views::filter([](auto&& line) { return not line.empty(); })
        | ranges::to<std::vector<std::string>>();

    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<std::vector<std::string>>();
            return set{std::stoull(l[0]), std::stoull(l[1])};
        })
        | ranges::to<std::vector<set>>();

    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<std::string>()); })
        | ranges::to<std::vector>();

    // 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<set> merge_sets(std::vector<set> 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;
}