Skip to content

Commit fba7e14

Browse files
committed
11
1 parent b29b6cc commit fba7e14

File tree

3 files changed

+174
-4
lines changed

3 files changed

+174
-4
lines changed

cpp/11.cpp

+151
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,151 @@
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+
}

cpp/common.h

+17
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
#include <cstdio>
1010
#include <cstring>
1111
#include <deque>
12+
#include <fstream>
1213
#include <functional>
1314
#include <iostream>
1415
#include <iterator>
@@ -29,6 +30,22 @@
2930
using vs = std::vector<std::string>;
3031

3132
namespace gb::advent2021 {
33+
34+
// Sad state of c++ where range based iteration with split_view is just
35+
// impossible to work in gcc 11.3
36+
std::vector<std::string_view> split(const std::string &sentence,
37+
const std::string &delim) {
38+
std::vector<std::string_view> vs{};
39+
size_t s{0}, e{0};
40+
auto it = sentence.begin();
41+
while ((e = sentence.find(delim, s)) != std::string::npos) {
42+
vs.emplace_back(std::string_view{it, std::next(it, (e - s))});
43+
std::advance(it, (e - s) + delim.size());
44+
s = e + delim.size();
45+
}
46+
return vs;
47+
}
48+
3249
std::vector<std::string> readIn() {
3350
std::vector<std::string> lines;
3451
for (std::string l; getline(std::cin, l);) {

cpp/meson.build

+6-4
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
project('advent2022', 'cpp',
22
version : '0.1',
3-
default_options : ['warning_level=3', 'cpp_std=c++20'])
3+
default_options : ['warning_level=3', 'cpp_std=c++2b'])
44

55
executable('1',
66
'1.cpp',
@@ -42,9 +42,11 @@ executable('10',
4242
'10.cpp',
4343
dependencies: [])
4444

45-
# executable('11',
46-
# '11.cpp',
47-
# dependencies: [])
45+
# gmp = dependency('gmp')
46+
executable('11',
47+
'11.cpp',
48+
# dependencies: [gmp])
49+
dependencies: [])
4850

4951
# executable('12',
5052
# '12.cpp',

0 commit comments

Comments
 (0)