aoc24/05/main.cc
2024-12-05 13:12:43 +01:00

133 lines
No EOL
3.7 KiB
C++

#include <fstream>
#include <iostream>
#include <sstream>
#include <vector>
#include <map>
#include <set>
using namespace std;
// constraints maps n to all values that need to appear after n
bool checkUpdate(vector<int> update, map<int, set<int, greater<int>>> constraints) {
// holds all values that have been visited already in this update
vector<int> prev;
for (auto n : update) {
for (auto p : prev) {
if (constraints[n].count(p)) {
return false;
}
}
prev.push_back(n);
}
return true;
}
// parse constraints, aka lines of integer tuples separated by "|"
void parseConstraints(ifstream &input, map<int, set<int, greater<int>>> &constraints) {
string line;
while (getline(input, line) && line.size()) {
stringstream line_stream;
line_stream << line;
int a;
int b;
char c;
line_stream >> a;
// discard "|"
line_stream >> c;
line_stream >> b;
// add b to constraint set of a
if (constraints.count(a) == 0) {
set<int, greater<int>> constraint{b};
constraints.insert({a, constraint});
} else {
constraints[a].insert(b);
}
}
}
// parse updates, aka lines of comma separated values
void parseUpdates(ifstream &input, vector<vector<int>> &updates) {
string line;
while (getline(input, line)) {
// cout << "parseUpdates got line: " << line << endl;
int n;
stringstream line_stream;
line_stream << line;
vector<int> v;
while (line_stream >> n) {
v.push_back(n);
char c;
// discard comma
line_stream >> c;
}
updates.push_back(v);
}
}
// sums up the middle values of correct updates
int correctUpdates(map<int, set<int, greater<int>>> constraints, vector<vector<int>> updates) {
int sum = 0;
for (auto update : updates) {
if (checkUpdate(update, constraints)) {
sum += update[update.size() / 2];
}
}
return sum;
}
// corrects an incorrect update by doing something akin to bubble sort
// (aka swapping rule violating pairs until there are none left)
void correction(vector<int> &update, map<int, set<int, greater<int>>> constraints) {
for (int i = 0; i < update.size(); i++) {
for (int j = 0; j < i; j++) {
if (constraints[update[i]].count(update[j])) {
// swap n and p, then start over
int temp = update[i];
update[i] = update[j];
update[j] = temp;
correction(update, constraints);
return;
}
}
}
}
// sums up the middle values of incorrect updates after correcting them
int incorrectUpdates(map<int, set<int, greater<int>>> constraints, vector<vector<int>> updates) {
int sum = 0;
for (auto update : updates) {
if (!checkUpdate(update, constraints)) {
correction(update, constraints);
sum += update[update.size() / 2];
}
}
return sum;
}
int main(int argc, char *argv[]) {
ifstream example("example");
ifstream input("input");
map<int, set<int, greater<int>>> constraints_example;
vector<vector<int>> updates_example;
parseConstraints(example, constraints_example);
parseUpdates(example, updates_example);
cout << "Update sum (example) is: " << correctUpdates(constraints_example, updates_example) << endl;
cout << "Corrected update sum (example) is: " << incorrectUpdates(constraints_example, updates_example) << endl;
map<int, set<int, greater<int>>> constraints_input;
vector<vector<int>> updates_input;
parseConstraints(input, constraints_input);
parseUpdates(input, updates_input);
cout << "Update sum (input) is: " << correctUpdates(constraints_input, updates_input) << endl;
cout << "Corrected update sum (input) is: " << incorrectUpdates(constraints_input, updates_input) << endl;
return 0;
}