diff --git a/puzzles/training/airport_routes.cpp b/puzzles/training/airport_routes.cpp new file mode 100644 index 0000000..c59638d --- /dev/null +++ b/puzzles/training/airport_routes.cpp @@ -0,0 +1,178 @@ +/* +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 +#include +#include +#include +#include +#include +#include +#include + +/* +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> 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 visited; + std::vector path; + + print_all_routes_helper(start, destination, visited, path, + [](const std::vector& 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& visited, + std::vector& path, + std::function& 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 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; +}}