Line data Source code
1 : #include "LinewiseInput.h"
2 : #include "PuzzleImpl.h"
3 :
4 : #include <bits/ranges_algo.h>
5 : #include <functional>
6 : #include <libassert/assert.hpp>
7 : #include <ranges>
8 : #include <re2/re2.h>
9 :
10 : #include <fmt/format.h>
11 : #include <fmt/ranges.h>
12 :
13 : #include <algorithm>
14 : #include <numeric>
15 : #include <tuple>
16 :
17 : namespace {
18 :
19 2000 : std::array<int, 2u> parse(std::string_view const s) {
20 2000 : static RE2 const pattern = R"((\d+) (\d+))";
21 2000 : std::array<int, 2u> numbers{0, 0};
22 2000 : ASSUME(RE2::FullMatch(s, pattern, &numbers[0], &numbers[1]));
23 2000 : return numbers;
24 2000 : }
25 :
26 2 : std::array<std::vector<int>, 2u> parseAndSortVectors(std::string_view const input) {
27 2 : std::vector<int> left, right;
28 :
29 2000 : for (auto [l, r] : getLineWise(input) | std::views::transform(parse)) {
30 2000 : left.push_back(l);
31 2000 : right.push_back(r);
32 2000 : }
33 :
34 2 : std::ranges::sort(left);
35 2 : std::ranges::sort(right);
36 :
37 2 : return {std::move(left), std::move(right)};
38 2 : }
39 :
40 : } // namespace
41 :
42 1 : template <> size_t part1<2024, 1>(std::string_view const input) {
43 1 : auto [left, right] = parseAndSortVectors(input);
44 :
45 1 : return std::ranges::fold_left(
46 1000 : std::views::zip_transform([](int const l, int const r) { return std::abs(l - r); }, left,
47 1 : right),
48 1 : size_t(0), std::plus{});
49 1 : }
50 :
51 1 : template <> size_t part2<2024, 1>(std::string_view const input) {
52 1 : auto [left, right] = parseAndSortVectors(input);
53 :
54 1 : return std::ranges::fold_left(
55 1 : left | std::views::chunk_by(std::ranges::equal_to{}) |
56 1000 : std::views::transform([rIt = right.begin(), &right](auto &&chunkFromLeft) mutable {
57 1000 : int const l = *std::ranges::begin(chunkFromLeft);
58 1000 : auto chunkFromRight = std::ranges::equal_range(rIt, right.end(), l);
59 1000 : rIt = std::ranges::end(chunkFromRight);
60 1000 : return l * std::ranges::size(chunkFromLeft) * std::ranges::size(chunkFromRight);
61 1000 : }),
62 1 : size_t(0), std::plus{});
63 1 : }
|