133 lines
No EOL
3.7 KiB
C++
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;
|
|
} |