#include #include #include #include "Reader.h" const std::string& Reader::getName(int id) { return names[id]; } const std::vector& Reader::operator[](int x) const { return distances[x]; } int Reader::getSize() const { return ids; } int Reader::getOrAddId(const std::string& s) { auto found = nameToId.find(s); if(found != nameToId.end()) { return found->second; } int id = ids++; nameToId[s] = id; for(std::vector& inner : distances) { inner.push_back(-1); } distances.push_back(std::vector(ids, -1)); distances.back()[ids - 1] = 0; names.push_back(s); return id; } std::string Reader::trim(const std::string& s) const { size_t start = 0; while(start < s.length() && s[start] == ' ') { start++; } size_t end = s.length(); while(end > 0 && s[end - 1] == ' ') { end--; } return s.substr(start, end - start); } bool Reader::read(const char* path) { std::ifstream in; in.open(path); if(!in.good()) { std::cout << "cannot find data\n"; return true; } while(!in.eof()) { std::string s; std::getline(in, s); if(s.find("road(", 0) != 0) { continue; } s = s.substr(5, s.length() - 5); size_t fromIndex = s.find(",", 0); if(fromIndex == s.npos) { continue; } size_t toIndex = s.find(",", fromIndex + 1); if(toIndex == s.npos) { continue; } size_t distanceIndex = s.find(")", toIndex + 1); if(distanceIndex == s.npos) { continue; } std::string from = trim(s.substr(0, fromIndex)); std::string to = trim(s.substr(fromIndex + 1, toIndex - fromIndex - 1)); std::string distanceString = trim(s.substr(toIndex + 1, distanceIndex - toIndex - 1)); int fromId = getOrAddId(from); int toId = getOrAddId(to); int distance = std::stoi(distanceString); distances[fromId][toId] = distance; distances[toId][fromId] = distance; } for(int i = 0; i < ids; i++) { distance(i); } return false; } void Reader::print() const { for(size_t x = 0; x < distances.size(); x++) { for(size_t y = 0; y < distances[x].size(); y++) { printf("%3d ", distances[x][y]); } std::cout << "\n"; } } struct Node { int distance = INT_MAX; bool visited = false; }; static bool notAllVisited(const std::vector& nodes) { for(const Node& n : nodes) { if(!n.visited) { return true; } } return false; } void Reader::distance(int column) { std::vector nodes(ids, Node()); nodes[column].distance = 0; while(notAllVisited(nodes)) { size_t minIndex = 0; int minDistance = INT_MAX; for(size_t i = 0; i < nodes.size(); i++) { if(!nodes[i].visited && nodes[i].distance < minDistance) { minIndex = i; minDistance = nodes[i].distance; } } nodes[minIndex].visited = true; for(int i = 0; i < ids; i++) { if(!nodes[i].visited && distances[minIndex][i] != -1) { int newDistance = minDistance + distances[minIndex][i]; if(newDistance < nodes[i].distance) { nodes[i].distance = newDistance; } } } } for(size_t i = 0; i < nodes.size(); i++) { distances[column][i] = nodes[i].distance; } }