1
+ #include " common.h"
2
+ #include < gmpxx.h>
3
+
4
+ // I SOLVED THE PROBLEM BUT WAS TRYING TO BE AS FUNCTIONAL AS POSSIBLE BUT.. c++
5
+ namespace {
6
+ constexpr size_t MaxSize{1024 };
7
+ #define ASSERT_SCAN (expr, err ) \
8
+ if ((expr) == 0 ) \
9
+ throw std::runtime_error ((err));
10
+
11
+ size_t play (long &worry, auto amplify, auto pacify, int test, size_t test_true,
12
+ size_t test_false) {
13
+ worry = amplify (worry);
14
+ worry = pacify (worry);
15
+ return ((worry % test) == 0 ) ? test_true : test_false;
16
+ };
17
+
18
+ struct Monkey {
19
+ decltype (play) play;
20
+ long inspects{};
21
+ };
22
+
23
+ // parse with input
24
+ // send the mkys array
25
+ // send the items array
26
+ void parse (const auto &input, auto &mkys, auto &items) {
27
+ using namespace std ::placeholders;
28
+
29
+ for (size_t i{0 }; i < input.size (); i += 7 ) {
30
+ size_t j = i / 7UL ;
31
+ auto &m = mkys[j];
32
+ {
33
+ std::istringstream ss{input[i + 1 ]};
34
+ std::string s, _;
35
+ ss >> _ >> _;
36
+ while (ss >> s) {
37
+ if (s[s.size () - 1 ] == ' ,' )
38
+ s.resize (s.size () - 1 );
39
+ long l{};
40
+ std::from_chars (s.data (), s.data () + s.size (), l);
41
+ items.emplace_back (std::make_tuple (j, l));
42
+ }
43
+ }
44
+
45
+ char c;
46
+ long w;
47
+ auto scans = std::sscanf (input[i + 2 ].c_str (),
48
+ " Operation: new = old %c %d" , &c, &w);
49
+ switch (c) {
50
+ case ' +' :
51
+ auto f = std::bind (std::plus{}, w, _1);
52
+ m.play = std::bind (play, _1, f, _2, _3, _4, _5);
53
+ break ;
54
+ case ' *' :
55
+ if (scans != 2 ) {
56
+ auto f = [](long worry) { return std::multiplies{}(worry, worry); };
57
+ m.play = std::bind (play, _1, f, _2, _3, _4, _5)
58
+ } else {
59
+ auto f = std::bind (std::multiplies{}, w, _1);
60
+ m.play = std::bind (play, _1, f, _2, _3, _4, _5)
61
+ }
62
+ default :
63
+ throw std::runtime_error (" unknow operator " + m.op );
64
+ }
65
+
66
+ int t;
67
+ size_t tt, tf;
68
+ ASSERT_SCAN (
69
+ std::sscanf (input[i + 3 ].c_str (), " Test: divisible by %d" , &t),
70
+ " no test" );
71
+ ASSERT_SCAN (std::sscanf (input[i + 4 ].c_str (),
72
+ " If true: throw to monkey %lu" , &tt),
73
+ " no true" );
74
+ ASSERT_SCAN (std::sscanf (input[i + 5 ].c_str (),
75
+ " If false: throw to monkey %lu" , &tf),
76
+ " no false" );
77
+ std::bind (m.play , _1, _2, t, tt, tf);
78
+ }
79
+ }
80
+
81
+ template <size_t N, size_t M> long p1 (const auto &input) {
82
+ std::array<Monkey, M> mkys{};
83
+ std::vector<std::tuple<size_t , long >> items{};
84
+ for (size_t i{0 }; i < input.size (); i += 7 ) {
85
+ size_t j = i / 7UL ;
86
+ Monkey &m = mkys[j];
87
+ {
88
+ std::istringstream ss{input[i + 1 ]};
89
+ std::string s, _;
90
+ ss >> _ >> _;
91
+ while (ss >> s) {
92
+ if (s[s.size () - 1 ] == ' ,' )
93
+ s.resize (s.size () - 1 );
94
+ long l{};
95
+ std::from_chars (s.data (), s.data () + s.size (), l);
96
+ items.emplace_back (std::make_tuple (j, l));
97
+ }
98
+ }
99
+ if (std::sscanf (input[i + 2 ].c_str (), " Operation: new = old %c %d" , &m.op ,
100
+ &m.wrry ) != 2 ) {
101
+ m.op = ' ^' ;
102
+ }
103
+ ASSERT_SCAN (
104
+ std::sscanf (input[i + 3 ].c_str (), " Test: divisible by %d" , &m.test ),
105
+ " no test" );
106
+ ASSERT_SCAN (std::sscanf (input[i + 4 ].c_str (),
107
+ " If true: throw to monkey %lu" , &m.test_true ),
108
+ " no true" );
109
+ ASSERT_SCAN (std::sscanf (input[i + 5 ].c_str (),
110
+ " If false: throw to monkey %lu" , &m.test_false ),
111
+ " no false" );
112
+ }
113
+
114
+ for (size_t _ = 0 ; _ < N; ++_) {
115
+ for (size_t i = 0 ; i < M; ++i) {
116
+ auto &m = mkys[i];
117
+ long ins{};
118
+ for (auto &item :
119
+ items | std::ranges::views::filter (
120
+ [&i](const auto &it) { return std::get<0 >(it) == i; })) {
121
+ auto &w = std::get<1 >(item);
122
+ switch (m.op ) {
123
+ case ' *' :
124
+ w *= m.wrry ;
125
+ break ;
126
+ case ' +' :
127
+ w += m.wrry ;
128
+ break ;
129
+ case ' ^' :
130
+ w *= w;
131
+ break ;
132
+ default :
133
+ throw std::runtime_error (" unknow operator " + m.op );
134
+ }
135
+ w %= (11 * 5 * 19 * 13 * 7 * 17 * 2 * 3 );
136
+ const auto &tgt = ((w % m.test ) == 0 ) ? m.test_true : m.test_false ;
137
+ std::get<0 >(item) = tgt;
138
+ ++ins;
139
+ }
140
+ m.inspects += ins;
141
+ }
142
+ }
143
+ std::ranges::sort (mkys, std::ranges::greater (), &Monkey::inspects);
144
+ return mkys[0 ].inspects * mkys[1 ].inspects ;
145
+ }
146
+ } // namespace
147
+
148
+ int main () {
149
+ const auto &input = gb::advent2021::readIn ();
150
+ gb::advent2021::writeOut (std::to_string (p1<10000 , 8 >(input)));
151
+ }
0 commit comments