Day 5: Part 1
This commit is contained in:
parent
9c2183d413
commit
3e2c5d55c9
195
Aufgabe 5/main.cpp
Normal file
195
Aufgabe 5/main.cpp
Normal file
@ -0,0 +1,195 @@
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
#include <fstream>
|
||||
#include <unordered_map>
|
||||
#include <unordered_set>
|
||||
#include <queue>
|
||||
|
||||
|
||||
struct Rule{
|
||||
int first;
|
||||
int second;
|
||||
|
||||
Rule(int first, int second) : first(first), second(second) {}
|
||||
};
|
||||
|
||||
struct Update {
|
||||
std::vector<int> pages;
|
||||
|
||||
explicit Update(const std::vector<int> &pages) : pages(pages) {}
|
||||
};
|
||||
|
||||
std::vector<std::string> readTextFromFile(const std::string& fileName) {
|
||||
std::vector<std::string> lines;
|
||||
std::ifstream file(fileName);
|
||||
if (!file) { // Überprüft, ob die Datei geöffnet werden konnte
|
||||
std::cerr << "Fehler: Datei konnte nicht geöffnet werden: " << fileName << std::endl;
|
||||
return lines;
|
||||
}
|
||||
std::string s;
|
||||
while(getline(file, s)) {
|
||||
lines.push_back(s);
|
||||
}
|
||||
return lines;
|
||||
}
|
||||
|
||||
std::vector<std::string> splitString(const std::string& input, char ch) {
|
||||
std::vector<std::string> splittedString;
|
||||
size_t pos = input.find(ch);
|
||||
size_t initialPos = 0;
|
||||
|
||||
while(pos != std::string::npos) {
|
||||
splittedString.push_back(input.substr(initialPos, pos - initialPos));
|
||||
initialPos = pos + 1;
|
||||
pos = input.find(ch, initialPos);
|
||||
}
|
||||
|
||||
splittedString.push_back(input.substr(initialPos, std::min(pos, input.size()) - initialPos));
|
||||
|
||||
return splittedString;
|
||||
}
|
||||
|
||||
std::vector<Rule> parseRules(std::vector<std::string>& input) {
|
||||
std::vector<Rule> rules;
|
||||
|
||||
for(const auto& line : input) {
|
||||
if(line.find('|') != std::string::npos) {
|
||||
std::vector<std::string> splittedLine = splitString(line, '|');
|
||||
int first = std::stoi(splittedLine[0]);
|
||||
int second = std::stoi(splittedLine[1]);
|
||||
rules.emplace_back(first, second);
|
||||
}
|
||||
}
|
||||
return rules;
|
||||
}
|
||||
|
||||
std::vector<Update> parseUpdates(std::vector<std::string>& input) {
|
||||
std::vector<Update> updates;
|
||||
for(const auto& line : input) {
|
||||
if(line.find(',') != std::string::npos) {
|
||||
std::vector<std::string> splittedString = splitString(line, ',');
|
||||
std::vector<int> pages;
|
||||
for(const auto& page : splittedString) {
|
||||
pages.push_back(std::stoi(page));
|
||||
}
|
||||
updates.emplace_back(pages);
|
||||
}
|
||||
}
|
||||
return updates;
|
||||
}
|
||||
|
||||
std::vector<int> topologicalSort(const std::vector<Rule>& rules) {
|
||||
std::unordered_map<int, std::unordered_set<int>> adjList;
|
||||
std::unordered_map<int, int> inDegree;
|
||||
|
||||
// Step 1: Build the graph
|
||||
for(const auto& rule : rules) {
|
||||
adjList[rule.first].insert(rule.second);
|
||||
inDegree[rule.second]++;
|
||||
|
||||
if(inDegree.find(rule.first) == inDegree.end()) {
|
||||
inDegree[rule.first] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Step 2: Initialize queue with nodes having in degree 0
|
||||
std::queue<int> zeroInDegreeQueue;
|
||||
for(const auto& pair : inDegree) {
|
||||
if(pair.second == 0) {
|
||||
zeroInDegreeQueue.push(pair.first);
|
||||
}
|
||||
}
|
||||
|
||||
//Step 3: Process nodes and generate topological order
|
||||
std::vector<int> topologicalOrder;
|
||||
while(!zeroInDegreeQueue.empty()) {
|
||||
int current = zeroInDegreeQueue.front();
|
||||
zeroInDegreeQueue.pop();
|
||||
topologicalOrder.push_back(current);
|
||||
|
||||
if(adjList.find(current) != adjList.end()) {
|
||||
for(const auto& neighbor : adjList[current]) {
|
||||
inDegree[neighbor]--;
|
||||
if(inDegree[neighbor] == 0) {
|
||||
zeroInDegreeQueue.push(neighbor);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return topologicalOrder;
|
||||
}
|
||||
|
||||
int indexOf(std::vector<int> vec, int element) {
|
||||
for(int i=0; i< vec.size(); i++) {
|
||||
if(vec[i] == element) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
//Checks whether a is before b in topological order
|
||||
bool isBefore(const std::vector<Rule>& rules, int a, int b) {
|
||||
for(const Rule& rule: rules) {
|
||||
if(rule.second == a && rule.first == b) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool isAfter(const std::vector<Rule>& rules, int a, int b) {
|
||||
for(const Rule& rule : rules) {
|
||||
if(rule.second == b && rule.first == a) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool isUpdateCorrect(const Update& update, const std::vector<Rule>& rules) {
|
||||
std::vector<int> topologicalOrder = topologicalSort(rules);
|
||||
//Check if all pages are printed after the previous one
|
||||
for(int i=0; i<update.pages.size(); i++) {
|
||||
for(int j=0; j<i; j++) {
|
||||
if(!isBefore(rules, update.pages[j], update.pages[i])) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
for(int j=i+1; j<update.pages.size(); j++) {
|
||||
if(!isAfter(rules, update.pages[j], update.pages[i])) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
std::vector<Update> determineCorrectUpdates(std::vector<Update>& updates, std::vector<Rule>& rules) {
|
||||
std::vector<Update> validUpdates;
|
||||
for(const Update& update : updates) {
|
||||
if(isUpdateCorrect(update, rules)) {
|
||||
validUpdates.push_back(update);
|
||||
}
|
||||
}
|
||||
return validUpdates;
|
||||
}
|
||||
|
||||
int calcMiddleSum(std::vector<Update>& updates) {
|
||||
int sum = 0;
|
||||
for(const auto& update: updates) {
|
||||
sum += update.pages[update.pages.size()/2];
|
||||
}
|
||||
return sum;
|
||||
}
|
||||
|
||||
int main() {
|
||||
std::vector<std::string> input = readTextFromFile("../input.txt");
|
||||
std::vector<Rule> rules = parseRules(input);
|
||||
std::vector<Update> updates = parseUpdates(input);
|
||||
std::vector<Update> correctUpdates = determineCorrectUpdates(updates, rules);
|
||||
int result = calcMiddleSum(correctUpdates);
|
||||
std::cout << "The middle sum of the correct Updates is: " << result << std::endl;
|
||||
return 0;
|
||||
}
|
Loading…
Reference in New Issue
Block a user