Advent of Code 2022 - 2nd attempt in c++
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

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;
}