diff --git a/roadmap/roadmap.cpp b/roadmap/roadmap.cpp index ab46585..37c568f 100644 --- a/roadmap/roadmap.cpp +++ b/roadmap/roadmap.cpp @@ -1,4 +1,15 @@ -// vim: set ts=4 sw=4 et tw=80: +// vim: set ts=3 sw=3 et tw=80: + +/* Assignment 4 - Chess paths + * Claudio Maggioni + * + * External sources used: + * - cppreference.com + * - DFS wikipedia implementation (adapted). + * + * The flag DEBUG, if defined, activates some debug messages printe on stdout. + * This is disabled to comply with tests. + */ #include "roadmap.h" #include @@ -8,146 +19,163 @@ #include using namespace std; - +#define DEBUG 1 class ConcreteRoadMap : public AbstractRoadMap { - private: - map< string, set > adj; + private: + map< string, set > adj; - /* - * Adds in the map for key city1 a new set with city2 inside if there is - * no prior set, otherwise it appends city2 into the existing set - */ - void addPair(const string& city1, const string& city2) { - this->adj[city1].insert(city2); - } + /* + * Adds in the map for key city1 a new set with city2 inside if there is + * no prior set, otherwise it appends city2 into the existing set + */ + void addPair(const string& city1, const string& city2) { + this->adj[city1].insert(city2); + } - public: - ConcreteRoadMap() : adj() {}; + public: + ConcreteRoadMap() : adj() {}; - void addRoad(const string& city1, const string& city2) override { - addPair(city1, city2); - addPair(city2, city1); - } + void addRoad(const string& city1, const string& city2) override; - void addRoad(const vector& cities) override { - for (size_t i = 0; i < cities.size() - 1; i++) { - addRoad(cities[i], cities[i + 1]); - } - } + void addRoad(const vector& cities) override; - void clear() override { - this->adj.clear(); - } + void clear() override; - int neighborCountForCity(const string& city) const override { - auto i = this->adj.find(city); - if (i == adj.end()) return -1; - return i->second.size(); - } + int neighborCountForCity(const string& city) const override; - bool hasLoop() const override { - stack< std::pair > s; - set discovered; - bool search_comp; + bool hasLoop() const override; - for (auto itr = adj.begin(); itr != adj.end(); ++itr) { - search_comp = true; - s.push(std::pair(itr->first, itr->first)); - while (!s.empty()) { - const std::pair v = s.top(); -#if DEBUG - std::cout << "Front is: " << v.first << " with parent " << - v.second << "\n"; -#endif - s.pop(); - if (discovered.find(v.first) == discovered.end()) { - search_comp = false; - discovered.insert(v.first); - const auto i = this->adj.find(v.first); - const auto set = i->second; - for (auto j = set.begin(); j != set.end(); ++j) { - if (*j != v.second) { -#if DEBUG - cout << "Neighbor: " << *j << " parent: " << - v.first << "\n"; -#endif - s.push(std::pair(*j, - v.first)); - } - } - } else if (!search_comp) { - // cout << v.first << " is discovered\n"; - return true; - } - } - } - return false; - } + bool reachable(const string& c1, const string& c2) const override; - bool reachable(const string& c1, const string& c2) const override { - if (adj.find(c1) == adj.end() || - adj.find(c2) == adj.end()) { - return false; - } - - deque s; - set discovered; - s.push_back(c1); - while (!s.empty()) { - const string& v = s.front(); - if (v == c2) return true; - s.pop_front(); - - discovered.insert(v); - const auto i = this->adj.find(v); - const auto set = i->second; - for (auto j = set.begin(); j != set.end(); ++j) { - if (discovered.find(*j) == discovered.end()) { - s.push_back(*j); - } - } - } - return false; - } - - int countIslands() const override { - int islands = 0; - bool first; - - stack< std::pair > s; - set discovered; - - for (auto itr = adj.begin(); itr != adj.end(); ++itr) { - s.push(std::pair(itr->first, itr->first)); - first = true; - while (!s.empty()) { - const std::pair& v = s.top(); - s.pop(); - if (discovered.find(v.first) == discovered.end()) { - - if (first) { - islands++; - } - - discovered.insert(v.first); - const auto i = this->adj.find(v.first); - const auto set = i->second; - - for (auto j = set.begin(); j != set.end(); ++j) { - if (*j != v.second) { - s.push(std::pair(*j, v.first)); - } - } - } - - first = false; - } - } - - return islands; - } + int countIslands() const override; }; -AbstractRoadMap* createRoadMap() { - return new ConcreteRoadMap(); + +void ConcreteRoadMap::addRoad(const string& city1, const string& city2) { + addPair(city1, city2); + addPair(city2, city1); +} + +void ConcreteRoadMap::addRoad(const vector& cities) { + for (size_t i = 0; i < cities.size() - 1; i++) { + addRoad(cities[i], cities[i + 1]); + } +} + +void ConcreteRoadMap::clear() { + adj.clear(); +} + +int ConcreteRoadMap::neighborCountForCity(const string& city) const { + auto i = this->adj.find(city); + if (i == adj.end()) return -1; + return i->second.size(); +} + +bool ConcreteRoadMap::hasLoop() const { + stack< std::pair > s; + set discovered; + bool search_comp; + + for (auto itr = adj.begin(); itr != adj.end(); ++itr) { + search_comp = true; + s.push(std::pair(itr->first, itr->first)); + while (!s.empty()) { + const std::pair v = s.top(); +#if DEBUG + std::cout << "Front is: " << v.first << " with parent " << + v.second << "\n"; +#endif + s.pop(); + if (discovered.find(v.first) == discovered.end()) { + search_comp = false; + discovered.insert(v.first); + const auto i = this->adj.find(v.first); + const auto set = i->second; + for (auto j = set.begin(); j != set.end(); ++j) { + if (*j != v.second) { +#if DEBUG + cout << "Neighbor: " << *j << " parent: " << + v.first << "\n"; +#endif + s.push(std::pair(*j, + v.first)); + } + } + } else if (!search_comp) { +#if DEBUG + cout << v.first << " is discovered\n"; +#endif + return true; + } + } + } + return false; +} + +bool ConcreteRoadMap::reachable(const string& c1, const string& c2) const { + if (adj.find(c1) == adj.end() || + adj.find(c2) == adj.end()) { + return false; + } + + deque s; + set discovered; + s.push_back(c1); + while (!s.empty()) { + const string& v = s.front(); + if (v == c2) return true; + s.pop_front(); + + discovered.insert(v); + const auto i = this->adj.find(v); + const auto set = i->second; + for (auto j = set.begin(); j != set.end(); ++j) { + if (discovered.find(*j) == discovered.end()) { + s.push_back(*j); + } + } + } + return false; +} + +int ConcreteRoadMap::countIslands() const { + int islands = 0; + bool first; + + stack< std::pair > s; + set discovered; + + for (auto itr = adj.begin(); itr != adj.end(); ++itr) { + s.push(std::pair(itr->first, itr->first)); + first = true; + while (!s.empty()) { + const std::pair& v = s.top(); + s.pop(); + if (discovered.find(v.first) == discovered.end()) { + + if (first) { + islands++; + } + + discovered.insert(v.first); + const auto i = this->adj.find(v.first); + const auto set = i->second; + + for (auto j = set.begin(); j != set.end(); ++j) { + if (*j != v.second) { + s.push(std::pair(*j, v.first)); + } + } + } + + first = false; + } + } + + return islands; +} + +AbstractRoadMap* createRoadMap() { + return new ConcreteRoadMap(); }