Line data Source code
1 : #include "IntegerCast.h"
2 : #include "LinewiseInput.h"
3 : #include "PuzzleImpl.h"
4 :
5 : #include <libassert/assert.hpp>
6 : #include <re2/re2.h>
7 :
8 : #include <algorithm>
9 : #include <cctype>
10 : #include <numeric>
11 : #include <ranges>
12 : #include <string_view>
13 :
14 : namespace {
15 :
16 : struct Interval {
17 : size_t min = 0u;
18 : size_t max = 0u;
19 : };
20 :
21 1000 : bool fullOverlap(Interval a, Interval b) {
22 1000 : if (a.min < b.min)
23 445 : return a.max >= b.max;
24 555 : else if (b.min < a.min)
25 392 : return b.max >= a.max;
26 163 : else
27 163 : return true;
28 1000 : }
29 :
30 1000 : bool overlap(Interval a, Interval b) {
31 1000 : if (a.min < b.min)
32 445 : return a.max >= b.min;
33 555 : else if (b.min < a.min)
34 392 : return b.max >= a.min;
35 163 : else
36 163 : return true;
37 1000 : }
38 :
39 2000 : std::array<Interval, 2u> parse(std::string_view const s) {
40 2000 : Interval a, b;
41 2000 : static RE2 const boxPattern(R"((\d+)-(\d+),(\d+)-(\d+))");
42 2000 : ASSUME(RE2::FullMatch(s, boxPattern, &a.min, &a.max, &b.min, &b.max));
43 2000 : return {a, b};
44 2000 : }
45 :
46 : } // namespace
47 :
48 1 : template <> size_t part1<2022, 4>(std::string_view const input) {
49 1 : return std::ranges::distance(
50 1 : input | std::views::split('\n') |
51 1000 : std::views::transform([](auto &&r) { return parse(std::string_view(r)); }) |
52 1 : std::views::filter(
53 1000 : [](auto const intervals) { return fullOverlap(intervals[0], intervals[1]); }));
54 1 : }
55 :
56 1 : template <> size_t part2<2022, 4>(std::string_view const input) {
57 1 : return std::ranges::distance(
58 1 : input | std::views::split('\n') |
59 1000 : std::views::transform([](auto &&r) { return parse(std::string_view(r)); }) |
60 1000 : std::views::filter([](auto const intervals) { return overlap(intervals[0], intervals[1]); }));
61 1 : }
|