Skip to content

Commit f5e4440

Browse files
committed
13
1 parent 59f630b commit f5e4440

File tree

2 files changed

+99
-3
lines changed

2 files changed

+99
-3
lines changed

cpp/13.cpp

+96
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
#include "common.h"
2+
3+
namespace {
4+
struct Packet;
5+
using Packets = std::vector<Packet>;
6+
struct Packet {
7+
std::variant<int, Packets> d;
8+
};
9+
10+
Packet _parse(const std::string &str, size_t &begin) {
11+
Packets pkts{};
12+
while (str[begin] != ']') {
13+
if (str[begin] == '[') {
14+
pkts.emplace_back(_parse(str, ++begin));
15+
} else if (str[begin] == ',') {
16+
++begin;
17+
} else {
18+
int i;
19+
std::istringstream ss{str};
20+
ss.seekg(begin, std::ios_base::beg);
21+
ss >> i;
22+
pkts.emplace_back(i);
23+
begin = ss.tellg();
24+
}
25+
}
26+
++begin;
27+
return Packet{pkts};
28+
}
29+
30+
Packet parse(const std::string &str) {
31+
size_t s{1};
32+
return _parse(str, s);
33+
}
34+
35+
int compare(const Packet &p1, const Packet &p2) {
36+
if (std::holds_alternative<Packets>(p1.d) &&
37+
std::holds_alternative<Packets>(p2.d)) {
38+
const auto &pkts1 = std::get<Packets>(p1.d);
39+
const auto &pkts2 = std::get<Packets>(p2.d);
40+
size_t i{0}, j{0};
41+
for (; i < pkts1.size() && j < pkts2.size(); ++i, ++j) {
42+
if (int r{}; (r = compare(pkts1[i], pkts2[j])) != 0)
43+
return r;
44+
}
45+
return compare(Packet{static_cast<int>(pkts1.size() - i)},
46+
Packet{static_cast<int>(pkts2.size() - j)});
47+
} else if (std::holds_alternative<Packets>(p1.d)) {
48+
return compare(p1, Packet{Packets{p2}});
49+
} else if (std::holds_alternative<Packets>(p2.d)) {
50+
return compare(Packet{Packets{p1}}, p2);
51+
}
52+
ASSERT_EXPR(std::holds_alternative<int>(p1.d), "p1 not int");
53+
ASSERT_EXPR(std::holds_alternative<int>(p2.d), "p2 not int");
54+
return (std::get<int>(p1.d) < std::get<int>(p2.d)) -
55+
(std::get<int>(p2.d) < std::get<int>(p1.d));
56+
}
57+
58+
long p1(const auto &input) {
59+
long res{0};
60+
for (size_t i{0}; i < input.size(); i += 3) {
61+
const auto &pkt1 = parse(input[i]);
62+
const auto &pkt2 = parse(input[i + 1]);
63+
res += (compare(pkt1, pkt2) > 0) ? ((i / 3) + 1) : 0;
64+
}
65+
return res;
66+
}
67+
68+
long p2(auto input) {
69+
input.emplace_back("[[2]]");
70+
input.emplace_back("[[6]]");
71+
auto comparer = [](std::string &a, std::string &b) {
72+
const auto &p1 = parse(a);
73+
const auto &p2 = parse(b);
74+
return compare(p1, p2) > 0;
75+
};
76+
std::vector<std::string> pkts;
77+
std::ranges::for_each(
78+
input | std::ranges::views::filter(
79+
[](const std::string &s) { return !s.empty(); }),
80+
[&pkts](const auto &pkt) { pkts.emplace_back(pkt); });
81+
std::ranges::sort(
82+
pkts,
83+
comparer); // one cannot simply sort the ouput of `views::filter` because
84+
// the `ranges::sort` requires a random access iterator whereas
85+
// the `filter` only produces a forward iterator
86+
size_t i = (std::ranges::find(pkts, "[[2]]") - pkts.begin()) + 1;
87+
size_t j = (std::ranges::find(pkts, "[[6]]") - pkts.begin()) + 1;
88+
return i * j;
89+
}
90+
} // namespace
91+
92+
int main() {
93+
const auto &input = gb::advent2021::readIn();
94+
gb::advent2021::writeOut(std::to_string(p1(input)));
95+
gb::advent2021::writeOut(std::to_string(p2(input)));
96+
}

cpp/meson.build

+3-3
Original file line numberDiff line numberDiff line change
@@ -52,9 +52,9 @@ executable('12',
5252
'12.cpp',
5353
dependencies: [])
5454

55-
# executable('13',
56-
# '13.cpp',
57-
# dependencies: [])
55+
executable('13',
56+
'13.cpp',
57+
dependencies: [])
5858

5959
# executable('14',
6060
# '14.cpp',

0 commit comments

Comments
 (0)