Line data Source code
1 : #include "PuzzleImpl.h"
2 :
3 : #include "IntegerCast.h"
4 : #include "Parsing.h"
5 : #include "Views.h"
6 :
7 : #include "experimental/mdspan"
8 : #include "fmt/format.h"
9 : #include "fmt/ranges.h"
10 :
11 : #include <algorithm>
12 : #include <cstddef>
13 : #include <map>
14 : #include <set>
15 : #include <string_view>
16 : #include <vector>
17 :
18 : using namespace std::literals;
19 :
20 : namespace {
21 :
22 7148000 : uint64_t next(uint64_t n) {
23 7148000 : constexpr uint64_t modulo = 16777216u;
24 7148000 : n ^= n << 6u;
25 7148000 : n %= modulo;
26 7148000 : n ^= n >> 5u;
27 7148000 : n %= modulo;
28 7148000 : n ^= n << 11u;
29 7148000 : return n % modulo;
30 7148000 : }
31 :
32 : } // namespace
33 :
34 1 : template <> size_t part1<2024, 22>(std::string_view const input) {
35 1 : std::vector<uint64_t> secretNumbers = parseIntegerRange<uint64_t>(input, '\n');
36 :
37 1 : for (auto &n : secretNumbers)
38 3575787 : for (unsigned i = 0; i < 2000; ++i) {
39 3574000 : n = next(n);
40 3574000 : }
41 :
42 1 : return std::ranges::fold_left(secretNumbers, uint64_t(0), std::plus{});
43 1 : }
44 :
45 1 : template <> size_t part2<2024, 22>(std::string_view const input) {
46 1 : std::vector<uint64_t> secretNumbers = parseIntegerRange<uint64_t>(input, '\n');
47 :
48 1 : using Extents = std::experimental::extents<int, 19u, 19u, 19u, 19u>;
49 1 : std::array<bool, integerCast<std::size_t>(19u * 19u * 19u * 19u)> priceChangesSeenData{};
50 1 : std::experimental::mdspan<bool, Extents> priceChangesSeen(priceChangesSeenData.data());
51 1 : priceChangesSeen = std::experimental::mdspan<bool, Extents>(&priceChangesSeen[9, 9, 9, 9]);
52 :
53 1 : std::array<int, integerCast<std::size_t>(19u * 19u * 19u * 19u)> seqPricesData{};
54 1 : std::experimental::mdspan<int, Extents> seqPrices(seqPricesData.data());
55 1 : seqPrices = std::experimental::mdspan<int, Extents>(&seqPrices[9, 9, 9, 9]);
56 :
57 1787 : for (auto &n : secretNumbers) {
58 1787 : std::ranges::fill(priceChangesSeenData, false);
59 1787 : int8_t lastPrice = 0;
60 1787 : std::array<int8_t, 4u> priceDelta{};
61 3575787 : for (unsigned i = 0; i < 2000; ++i) {
62 3574000 : n = next(n);
63 3574000 : auto const price = integerCast<int8_t>(n % 10);
64 3574000 : std::ranges::rotate(priceDelta, std::next(priceDelta.begin()));
65 3574000 : priceDelta.back() = integerCast<int8_t>(lastPrice - price);
66 3574000 : lastPrice = price;
67 :
68 3574000 : if (i > 3 && !priceChangesSeen[priceDelta]) {
69 3448949 : priceChangesSeen[priceDelta] = true;
70 3448949 : seqPrices[priceDelta] += price;
71 3448949 : }
72 3574000 : }
73 1787 : }
74 1 : return std::ranges::max(seqPricesData);
75 1 : }
|