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 <algorithm>
11 : #include <numeric>
12 : #include <string>
13 : #include <tuple>
14 :
15 : namespace {
16 :
17 2000 : std::array<int, 2u> parse(std::string_view const s) {
18 2000 : static RE2 const pattern = R"((\d+) (\d+))";
19 2000 : std::array<int, 2u> numbers{0, 0};
20 2000 : ASSUME(RE2::FullMatch(s, pattern, &numbers[0], &numbers[1]));
21 2000 : return numbers;
22 2000 : }
23 :
24 2 : std::array<std::vector<int>, 2u> parseAndSortVectors(std::string_view const input) {
25 2 : std::vector<int> left, right;
26 :
27 2000 : for (auto [l, r] : getLineWise(input) | std::views::transform(parse)) {
28 2000 : left.push_back(l);
29 2000 : right.push_back(r);
30 2000 : }
31 :
32 2 : std::ranges::sort(left);
33 2 : std::ranges::sort(right);
34 :
35 2 : return {std::move(left), std::move(right)};
36 2 : }
37 :
38 : } // namespace
39 :
40 1 : template <> std::string solvePart1<2024, 1>(std::string_view const input) {
41 1 : auto [left, right] = parseAndSortVectors(input);
42 :
43 1 : return std::to_string(std::ranges::fold_left(
44 1000 : std::views::zip_transform([](int const l, int const r) { return std::abs(l - r); }, left,
45 1 : right),
46 1 : size_t(0), std::plus{}));
47 1 : }
48 :
49 1 : template <> std::string solvePart2<2024, 1>(std::string_view const input) {
50 1 : auto [left, right] = parseAndSortVectors(input);
51 :
52 1 : return std::to_string(std::ranges::fold_left(
53 1 : left | std::views::chunk_by(std::ranges::equal_to{}) |
54 1000 : std::views::transform([rIt = right.begin(), &right](auto &&chunkFromLeft) mutable {
55 1000 : int const l = *std::ranges::begin(chunkFromLeft);
56 1000 : auto chunkFromRight = std::ranges::equal_range(rIt, right.end(), l);
57 1000 : rIt = std::ranges::end(chunkFromRight);
58 1000 : return l * std::ranges::size(chunkFromLeft) * std::ranges::size(chunkFromRight);
59 1000 : }),
60 1 : size_t(0), std::plus{}));
61 1 : }
|