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