179 lines
4.1 KiB
C++
179 lines
4.1 KiB
C++
/*
|
|
VIM: let b:cf5build="clang -std=c++20 -O2 -pthread -lstdc++ -I. {SRC} -o {OUT}"
|
|
VIM: let b:cf5run="{OUT}"
|
|
VIM-: let b:cppflags=g:Iboost.g:Itbb
|
|
VIM-: let b:ldflags=g:Lboost.g:Ltbb
|
|
VIM-: let b:ldlibpath=g:Bboost.g:Btbb
|
|
*/
|
|
#include <iostream>
|
|
#include <exception>
|
|
#include <chrono>
|
|
#include <string>
|
|
#include <vector>
|
|
#include <unordered_map>
|
|
#include <unordered_set>
|
|
#include <functional>
|
|
|
|
/*
|
|
Implement a class called AirMap that has two methods:
|
|
|
|
1- add_route(start, destination)
|
|
- adds a ONE WAY connecting flight from start to destination
|
|
|
|
2- print_all_routes(start, destination)
|
|
- prints all possible routes from start to destination irrespective of hops
|
|
|
|
Sample inputs - Expected outputs
|
|
Given the following flight routes, print all possible routes between the airports C and D
|
|
|
|
A ----> B
|
|
B ----> A
|
|
A ----> C
|
|
C ----> A
|
|
A ----> D
|
|
D ----> A
|
|
B ----> C
|
|
C ----> B
|
|
B ----> D
|
|
D ----> B
|
|
Expected output:
|
|
|
|
C,A,B,D,
|
|
C,A,D,
|
|
C,B,A,D,
|
|
C,B,D,
|
|
|
|
Input corner cases
|
|
Find all routes from A to C
|
|
|
|
No route example:
|
|
|
|
A ----> B
|
|
C ----> B
|
|
C ----> A
|
|
|
|
Expected output:
|
|
|
|
"No route was found" message or an empty output
|
|
Source equals destination example: Find all routes from A to A
|
|
|
|
A ----> B
|
|
B ----> C
|
|
C ----> A
|
|
Expected output:
|
|
|
|
A
|
|
*/
|
|
|
|
class AirMap
|
|
{
|
|
std::unordered_map<std::string, std::unordered_set<std::string>> graph_;
|
|
|
|
public:
|
|
void add_route(const std::string& start, const std::string& destination)
|
|
{
|
|
graph_[start].insert(destination);
|
|
}
|
|
|
|
void print_all_routes(
|
|
const std::string& start,
|
|
const std::string& destination) const
|
|
{
|
|
std::unordered_set<std::string> visited;
|
|
std::vector<std::string> path;
|
|
|
|
print_all_routes_helper(start, destination, visited, path,
|
|
[](const std::vector<std::string>& path){
|
|
for (const auto& node : path){
|
|
std::cout << node << ',';
|
|
}
|
|
std::cout << std::endl;
|
|
});
|
|
}
|
|
|
|
void print_all_routes_helper(
|
|
const std::string& start,
|
|
const std::string& destination,
|
|
std::unordered_set<std::string>& visited,
|
|
std::vector<std::string>& path,
|
|
std::function<void (const std::vector<std::string>& path)> fn) const
|
|
{
|
|
visited.insert(start);
|
|
path.push_back(start);
|
|
|
|
if (start == destination){
|
|
fn(path);
|
|
} else {
|
|
const auto it = graph_.find(start);
|
|
if ( it != graph_.end()){
|
|
for (const auto& node : it->second){
|
|
if ( !visited.contains(node) ){
|
|
print_all_routes_helper(node, destination, visited, path, fn);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
visited.erase(start);
|
|
path.pop_back();
|
|
}
|
|
};
|
|
|
|
int main ( void )
|
|
{try{
|
|
auto begin = std::chrono::high_resolution_clock::now();
|
|
|
|
|
|
AirMap map;
|
|
map.add_route("A","B");
|
|
map.add_route("B","A");
|
|
map.add_route("B","D");
|
|
map.add_route("A","D");
|
|
map.add_route("A","C");
|
|
map.add_route("C","A");
|
|
map.add_route("C","B");
|
|
map.add_route("B","C");
|
|
map.add_route("D","A");
|
|
map.add_route("D","B");
|
|
|
|
map.print_all_routes("C", "D");
|
|
//......
|
|
|
|
{
|
|
std::cout << "---------------------------------------" << std::endl;
|
|
AirMap map;
|
|
map.add_route("A","B");
|
|
map.add_route("C","A");
|
|
map.add_route("C","B");
|
|
map.print_all_routes("A", "C");
|
|
}
|
|
|
|
{
|
|
std::cout << "---------------------------------------" << std::endl;
|
|
AirMap map;
|
|
map.add_route("A","B");
|
|
map.add_route("B","C");
|
|
map.add_route("C","A");
|
|
map.print_all_routes("A", "A");
|
|
}
|
|
|
|
|
|
|
|
auto end = std::chrono::high_resolution_clock::now();
|
|
std::chrono::duration<double> seconds = end - begin;
|
|
std::cout << "Time: " << seconds.count() << std::endl;
|
|
return 0;
|
|
}
|
|
catch ( const std::exception& e )
|
|
{
|
|
std::cerr << std::endl
|
|
<< "std::exception(\"" << e.what() << "\")." << std::endl;
|
|
return 2;
|
|
}
|
|
catch ( ... )
|
|
{
|
|
std::cerr << std::endl
|
|
<< "unknown exception." << std::endl;
|
|
return 1;
|
|
}}
|