You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
143 lines
3.3 KiB
143 lines
3.3 KiB
2 years ago
|
#include <iostream>
|
||
|
#include <vector>
|
||
|
#include <array>
|
||
|
#include <algorithm>
|
||
|
|
||
|
using namespace std;
|
||
|
|
||
|
struct Packet : pair<unsigned, vector<Packet *>> {
|
||
|
unsigned &val = first;
|
||
|
vector<Packet *> &vec = second;
|
||
|
bool is_vec = false;
|
||
|
|
||
|
~Packet() { for (auto x : vec) delete x; }
|
||
|
};
|
||
|
|
||
|
struct Input : vector<Packet *> {
|
||
|
~Input() { for (auto x : *this) delete x; }
|
||
|
};
|
||
|
|
||
|
Packet *parse_packet(string::iterator it, string::iterator end)
|
||
|
{
|
||
|
Packet *p = new Packet();
|
||
|
if (it >= end) return p;
|
||
|
if (*it == '[') {
|
||
|
p->is_vec = true;
|
||
|
|
||
|
auto start = it + 1;
|
||
|
unsigned depth = 0;
|
||
|
for (it++; it < end; it++) {
|
||
|
if (!depth && start != it && (*it == ']' || *it == ',')) {
|
||
|
p->vec.push_back(parse_packet(start, it));
|
||
|
start = it + 1;
|
||
|
}
|
||
|
if (*it == '[') depth++;
|
||
|
if (*it == ']') if (!depth--) break;
|
||
|
}
|
||
|
} else {
|
||
|
p->val = stoi(string(it, end));
|
||
|
}
|
||
|
return p;
|
||
|
}
|
||
|
|
||
|
Input parse()
|
||
|
{
|
||
|
Input data;
|
||
|
for (string line; getline(cin, line);) {
|
||
|
if (line.empty()) continue;
|
||
|
data.push_back(parse_packet(line.begin(), line.end()));
|
||
|
}
|
||
|
return data;
|
||
|
}
|
||
|
|
||
|
int operator-(const Packet &l, const Packet &r)
|
||
|
{
|
||
|
Packet n;
|
||
|
|
||
|
const Packet *pl = &l;
|
||
|
const Packet *pr = &r;
|
||
|
|
||
|
if (pl->is_vec != pr->is_vec) {
|
||
|
Packet *nv = new Packet();
|
||
|
n.is_vec = true;
|
||
|
n.vec.push_back(nv);
|
||
|
if (!pl->is_vec) {
|
||
|
nv->val = pl->val;
|
||
|
pl = &n;
|
||
|
}
|
||
|
if (!pr->is_vec) {
|
||
|
nv->val = pr->val;
|
||
|
pr = &n;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (pl->is_vec && pr->is_vec) {
|
||
|
unsigned len = min(pl->vec.size(), pr->vec.size());
|
||
|
int diff = 0;
|
||
|
for (unsigned i = 0; i < len; i++) {
|
||
|
Packet *il = pl->vec[i];
|
||
|
Packet *ir = pr->vec[i];
|
||
|
diff = *il - *ir;
|
||
|
if (diff) break;
|
||
|
}
|
||
|
if (!diff) diff = pl->vec.size() - pr->vec.size();
|
||
|
return diff;
|
||
|
}
|
||
|
return pl->val - pr->val;
|
||
|
}
|
||
|
|
||
|
void print_packet(Packet *p)
|
||
|
{
|
||
|
if (p->is_vec) {
|
||
|
clog << '[';
|
||
|
for (unsigned i = 0; i < p->vec.size(); i++) {
|
||
|
if (i) clog << ',';
|
||
|
print_packet(p->vec[i]);
|
||
|
}
|
||
|
clog << ']';
|
||
|
} else {
|
||
|
clog << p->val;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
unsigned p1(const Input &input)
|
||
|
{
|
||
|
unsigned count = 0;
|
||
|
for (unsigned i = 0; i + 1 < input.size(); i += 2) {
|
||
|
if (*input[i] - *input[i + 1] < 0) count += (i / 2) + 1;
|
||
|
}
|
||
|
return count;
|
||
|
}
|
||
|
|
||
|
unsigned p2(const Input &input)
|
||
|
{
|
||
|
vector<Packet *> sorted = input;
|
||
|
|
||
|
string div1_s = "[[2]]";
|
||
|
string div2_s = "[[6]]";
|
||
|
Packet *div1 = parse_packet(div1_s.begin(), div1_s.end());
|
||
|
Packet *div2 = parse_packet(div2_s.begin(), div2_s.end());
|
||
|
sorted.push_back(div1);
|
||
|
sorted.push_back(div2);
|
||
|
|
||
|
sort(sorted.begin(), sorted.end(), [](Packet *l, Packet *r){ return *l - *r < 0; });
|
||
|
//for (auto i : sorted) {
|
||
|
//print_packet(i);
|
||
|
//clog << endl;
|
||
|
//}
|
||
|
|
||
|
unsigned div1_i = 1 + find(sorted.begin(), sorted.end(), div1) - sorted.begin();
|
||
|
unsigned div2_i = 1 + find(sorted.begin(), sorted.end(), div2) - sorted.begin();
|
||
|
|
||
|
delete div1;
|
||
|
delete div2;
|
||
|
return div1_i * div2_i;
|
||
|
}
|
||
|
|
||
|
int main()
|
||
|
{
|
||
|
auto input = parse();
|
||
|
cout << p1(input) << endl;
|
||
|
cout << p2(input) << endl;
|
||
|
}
|