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