8
8
#ifndef DAY22_HPP_A3Y597BB
9
9
#define DAY22_HPP_A3Y597BB
10
10
11
+ #include " lib.hpp" // for DEBUG
12
+ #include " unit_test/pretty_print.hpp" // for repr
13
+ #include " util/hash.hpp" // for make_hash
14
+
15
+ #include < algorithm> // for ranges::max_element
16
+ #include < array> // for array
17
+ #include < cstddef> // for size_t
18
+ #include < cstdint> // for uint8_t, uint32_t, uint64_t
19
+ #include < functional> // for hash
20
+ #include < iomanip> // for setw
21
+ #include < iostream> // for cerr
22
+ #include < unordered_map> // for unordered_map
23
+ #include < utility> // for pair (unordered_map)
24
+
25
+ namespace aoc ::day22 {
26
+ struct ChangeSequence : public std ::array<std::int8_t , 4 > {};
27
+ } // namespace aoc::day22
28
+
29
+ template <>
30
+ struct std ::hash<aoc::day22::ChangeSequence> {
31
+ std::size_t
32
+ operator ()(const aoc::day22::ChangeSequence &changes) const noexcept {
33
+ // random number (hexdump -n8 -e '"0x" 8/1 "%02x" "ull\n"'</dev/urandom)
34
+ std::size_t seed = 0xc17a07615bebc283ull ;
35
+ util::make_hash (seed, changes[0 ], changes[1 ], changes[2 ], changes[3 ]);
36
+ return seed;
37
+ }
38
+ };
39
+
11
40
namespace aoc ::day22 {
12
41
13
- void xorshift (long &secret, int shift) {
14
- long tmp = secret;
42
+ ChangeSequence add_price_change (const ChangeSequence &changes,
43
+ std::int8_t new_change) {
44
+ return ChangeSequence{changes[1 ], changes[2 ], changes[3 ], new_change};
45
+ }
46
+
47
+ class PriceSequence {
48
+ std::uint32_t secret;
49
+ int monkey_number;
50
+ ChangeSequence curr_changes{};
51
+ static std::unordered_map<ChangeSequence,
52
+ std::unordered_map<int , std::int8_t >>
53
+ sequence_prices;
54
+
55
+ void xorshift (int shift);
56
+
57
+ public:
58
+ explicit PriceSequence (std::uint32_t initial_secret, int monkey_number)
59
+ : secret(initial_secret), monkey_number(monkey_number) {}
60
+
61
+ void evolve (int iter);
62
+ std::uint32_t get_secret () const { return secret; }
63
+ std::int8_t get_price () const { return secret % 10 ; }
64
+
65
+ static int find_best_sell_sequence ();
66
+ };
67
+
68
+ void PriceSequence::xorshift (int shift) {
69
+ std::uint32_t tmp = secret;
15
70
if (shift < 0 ) {
16
71
tmp >>= -shift;
17
72
} else {
@@ -20,12 +75,47 @@ void xorshift(long &secret, int shift) {
20
75
secret = (secret ^ tmp) & 0xFF'FF'FF ;
21
76
}
22
77
23
- void evolve_secret (long &secret) {
24
- xorshift (secret, +6 );
25
- xorshift (secret, -5 );
26
- xorshift (secret, +11 );
78
+ void PriceSequence::evolve (int iter) {
79
+ // save previous price
80
+ std::int8_t old_price = secret % 10 ;
81
+ xorshift (+6 );
82
+ xorshift (-5 );
83
+ xorshift (+11 );
84
+ std::int8_t new_price = secret % 10 ;
85
+ curr_changes = add_price_change (curr_changes, new_price - old_price);
86
+ if (iter >= 3 ) {
87
+ // try_emplace does nothing if the key already exists
88
+ sequence_prices[curr_changes].try_emplace (monkey_number, new_price);
89
+ }
27
90
}
28
91
92
+ int PriceSequence::find_best_sell_sequence () {
93
+ const auto sell_sequence_value = [](const auto &entry) -> int {
94
+ int total = 0 ;
95
+ for (const auto &[_, price] : entry.second ) {
96
+ total += price;
97
+ }
98
+ return total;
99
+ };
100
+ auto it =
101
+ std::ranges::max_element (sequence_prices, {}, sell_sequence_value);
102
+ if constexpr (aoc::DEBUG) {
103
+ std::cerr << " best sequence: "
104
+ << pretty_print::repr<std::array<std::int8_t , 4 >>(
105
+ it->first , {.char_as_number = true })
106
+ << " \n " ;
107
+ std::cerr << " prices:\n " ;
108
+ for (const auto &[monkey, price] : it->second ) {
109
+ std::cerr << std::setw (5 ) << monkey << " : " << aoc::as_number (price)
110
+ << " \n " ;
111
+ }
112
+ }
113
+ return sell_sequence_value (*it);
114
+ }
115
+
116
+ std::unordered_map<ChangeSequence, std::unordered_map<int , std::int8_t >>
117
+ PriceSequence::sequence_prices{};
118
+
29
119
} // namespace aoc::day22
30
120
31
121
#endif /* end of include guard: DAY22_HPP_A3Y597BB */
0 commit comments