Line data Source code
1 : #include "../Puzzle.h"
2 : #include "../PuzzleImpl.h"
3 : #include "IntegerCast.h"
4 : #include "LinewiseInput.h"
5 :
6 : #include <libassert/assert.hpp>
7 : #include <re2/re2.h>
8 :
9 : #include <algorithm>
10 : #include <ranges>
11 : #include <string>
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 <> std::string solvePart1<2022, 4>(std::string_view const input) {
49 1 : return std::to_string(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 <> std::string solvePart2<2022, 4>(std::string_view const input) {
57 1 : return std::to_string(std::ranges::distance(
58 1 : input | std::views::split('\n') |
59 1000 : std::views::transform([](auto &&r) { return parse(std::string_view(r)); }) |
60 1 : std::views::filter(
61 1000 : [](auto const intervals) { return overlap(intervals[0], intervals[1]); })));
62 1 : }
|