delix777

Спринт 10. Транспортный справочник - структурируем код.

Nov 25th, 2025
47
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. -----------------------------------------------------------------------
  2. main.cpp
  3. -----------------------------------------------------------------------
  4. #include "transport_catalogue.h"
  5. #include "input_reader.h"
  6. #include "stat_reader.h"
  7.  
  8. using namespace std;
  9. using namespace transport_catalogue;
  10. using namespace transport_catalogue::detail;
  11.  
  12. int main() {
  13.     TransportCatalogue catalogue;
  14.     fill_catalogue(std::cin, catalogue);
  15.     parse_and_execute_queries(std::cin, catalogue);
  16. }
  17. -----------------------------------------------------------------------
  18. geo.h
  19. -----------------------------------------------------------------------
  20. #pragma once
  21. #include <cmath>
  22.  
  23. namespace transport_catalogue {
  24. namespace detail {
  25. namespace geo {
  26.    
  27. const int EARTH_RADIUS = 6371000;
  28. const double PI = 3.1415926535;
  29.    
  30. struct Coordinates {
  31.     double latitude;
  32.     double longitude;
  33.     bool operator==(const Coordinates& other) const {
  34.         return latitude == other.latitude
  35.             && longitude == other.longitude;
  36.     }
  37. };
  38.    
  39. inline double compute_distance(Coordinates start, Coordinates end) {
  40.     using namespace std;
  41.     if (!(start == end)) {
  42.         const double dr = PI / 180.;
  43.         return acos(sin(start.latitude * dr) * sin(end.latitude * dr)
  44.                     + cos(start.latitude * dr) * cos(end.latitude * dr)
  45.                     * cos(abs(start.longitude - end.longitude) * dr)) * EARTH_RADIUS;
  46.     } else {
  47.         return 0.0;
  48.     }
  49. }
  50.    
  51. }//end namespace geo
  52. }//end namespace detail
  53. }//end namespace transport_catalogue
  54. ---------------------------------------------------------------------
  55. input_reader.h
  56. -----------------------------------------------------------------------
  57. #pragma once
  58. #include "transport_catalogue.h"
  59.  
  60. namespace transport_catalogue {
  61. namespace detail {  
  62. namespace stop {
  63.     Stop parse_stop(const std::string& str);
  64.    
  65. }//end namespace stop
  66.    
  67. namespace distance {
  68.     std::vector<Distance> parse_distances(const std::string& str, TransportCatalogue& catalogue);
  69.    
  70. }//end namespace distance
  71.    
  72. namespace bus {
  73.     Bus parse_bus(std::string_view str, TransportCatalogue& catalogue);
  74.    
  75. }//end namespace bus
  76.  
  77. void fill_catalogue(std::istream& input, TransportCatalogue& catalogue);
  78.  
  79. }//end namespace detail
  80. }//end namespace transport_catalogue
  81. -----------------------------------------------------------------------
  82. stat_reader.h
  83. -----------------------------------------------------------------------
  84. #pragma once
  85. #include "transport_catalogue.h"
  86. #include <algorithm>
  87. #include <vector>
  88.  
  89. namespace transport_catalogue {
  90. namespace detail {
  91. namespace bus {
  92.    
  93. struct BusQueryResult{
  94.     std::string_view name;
  95.     bool not_found;
  96.     size_t stops_on_route;
  97.     size_t unique_stops;
  98.     size_t route_length;
  99.     double curvature;
  100. };
  101.    
  102. void show_terminal(BusQueryResult bus_info, std::ostream& output);
  103. BusQueryResult query(TransportCatalogue& catalogue, std::string_view str);
  104.    
  105. }//end namespace bus
  106.    
  107. namespace stop {
  108. struct StopQueryResult{
  109.     std::string_view name;
  110.     bool not_found;
  111.     std::vector <std::string_view> buses_name;
  112. };
  113.    
  114. void show_terminal(const StopQueryResult& stop_info, std::ostream& output);
  115. StopQueryResult query(TransportCatalogue& catalogue, std::string_view stop_name);
  116.    
  117. }//end namespace stop
  118.    
  119. void execute_query(TransportCatalogue& catalogue, std::string_view str);
  120. void parse_and_execute_queries(std::istream& input, TransportCatalogue& catalogue);
  121.    
  122. }//end namespace detail
  123. }//end namespace transport_catalogue
  124. -----------------------------------------------------------------------
  125. transport_catalogue.cpp
  126. -----------------------------------------------------------------------
  127. #include "transport_catalogue.h"
  128. #include <execution>
  129.  
  130. namespace transport_catalogue {  
  131.    
  132. void TransportCatalogue::add_stop(Stop&& stop) {
  133.     stops.push_back(std::move(stop));
  134.     Stop* stop_buf = &stops.back();
  135.     stopname_to_stop.insert(transport_catalogue::StopMap::value_type(stop_buf->name, stop_buf));
  136. }
  137.  
  138. void TransportCatalogue::add_bus(Bus&& bus) {
  139.     Bus* bus_buf;
  140.    
  141.     buses.push_back(std::move(bus));
  142.     bus_buf = &buses.back();
  143.     busname_to_bus.insert(BusMap::value_type(bus_buf->name, bus_buf));
  144.  
  145.     for (Stop* stop : bus_buf->stops) {
  146.          stop->buses.push_back(bus_buf);
  147.     }
  148.    
  149.     bus_buf->route_length = get_distance_to_bus(bus_buf);
  150. }
  151.  
  152. void TransportCatalogue::add_distance(const std::vector<Distance>& distances) {
  153.     for (auto distance : distances){
  154.         auto dist_pair = std::make_pair(distance.A, distance.B);
  155.         distance_to_stop.insert(DistanceMap::value_type(dist_pair, distance.distance));
  156.     }
  157. }
  158.  
  159. Bus* TransportCatalogue::get_bus(std::string_view bus_name) {  
  160.     if(busname_to_bus.empty()){
  161.         return nullptr;
  162.     }
  163.    
  164.     try{
  165.         return busname_to_bus.at(bus_name);
  166.     }
  167.     catch(const std::out_of_range &e){
  168.         return nullptr;
  169.     }
  170. }
  171.  
  172. Stop* TransportCatalogue::get_stop(std::string_view stop_name) {
  173.     if(stopname_to_stop.empty()){
  174.         return nullptr;
  175.     }
  176.    
  177.     try {
  178.         return stopname_to_stop.at(stop_name);
  179.     } catch(const std::out_of_range &e) {
  180.         return nullptr;
  181.     }
  182. }
  183.  
  184. std::unordered_set<const Stop*> TransportCatalogue::get_uniq_stops(Bus* bus) {
  185.     std::unordered_set<const Stop*> unique_stops;
  186.    
  187.     unique_stops.insert(bus->stops.begin(), bus->stops.end());
  188.    
  189.     return unique_stops;
  190. }
  191.  
  192. double TransportCatalogue::get_length(Bus* bus) {
  193.     return transform_reduce(next(bus->stops.begin()),
  194.                             bus->stops.end(),
  195.                             bus->stops.begin(),
  196.                             0.0,
  197.                             std::plus<>{},
  198.                             [](const Stop* lhs, const Stop* rhs) {
  199.                                 return detail::geo::compute_distance({(*lhs).latitude,
  200.                                                         (*lhs).longitude}, {(*rhs).latitude,
  201.                                                                               (*rhs).longitude});
  202.                             });
  203. }
  204.  
  205. std::unordered_set<const Bus*> TransportCatalogue::stop_get_uniq_buses(Stop* stop){    
  206.     std::unordered_set<const Bus*> unique_stops;    
  207.      
  208.     unique_stops.insert(stop->buses.begin(), stop->buses.end());  
  209.    
  210.     return unique_stops;
  211. }
  212.  
  213. size_t TransportCatalogue::get_distance_stop(const Stop* begin, const Stop* finish) {
  214.     if(distance_to_stop.empty()){
  215.         return 0;
  216.     }
  217.    
  218.     try {
  219.        
  220.         auto dist_pair = std::make_pair(begin, finish);
  221.         return distance_to_stop.at(dist_pair);
  222.        
  223.     } catch(const std::out_of_range &e) {
  224.        
  225.         try {
  226.             auto dist_pair = std::make_pair(finish, begin);
  227.             return distance_to_stop.at(dist_pair);
  228.         } catch(const std::out_of_range &e) {
  229.             return 0;    
  230.         }
  231.        
  232.     }
  233. }
  234.  
  235. size_t TransportCatalogue::get_distance_to_bus(Bus* bus) {
  236.     size_t distance = 0;
  237.     auto stops_size = bus->stops.size() - 1;
  238.     for (int i = 0; i < stops_size; i++) {
  239.         distance += get_distance_stop(bus->stops[i], bus->stops[i+1]);
  240.     }
  241.     return distance;
  242. }
  243.    
  244. }//end namespace transport_catalogue
  245. -----------------------------------------------------------------------
  246. transport_catalogue.h
  247. -----------------------------------------------------------------------
  248. #pragma once
  249. #include <deque>
  250. #include <string>
  251. #include <vector>
  252.  
  253. #include <iomanip>
  254. #include <iostream>
  255.  
  256. #include <unordered_set>
  257. #include <unordered_map>
  258.  
  259. #include "geo.h"
  260.  
  261. namespace transport_catalogue {  
  262.    
  263. struct Bus;
  264.    
  265. struct Stop {    
  266.     std::string name;
  267.     double latitude;
  268.     double longitude;
  269.    
  270.     std::vector<Bus*> buses;
  271. };
  272.  
  273. struct Bus {
  274.     std::string name;
  275.     std::vector<Stop*> stops;
  276.     size_t route_length;
  277. };
  278.  
  279. struct Distance {    
  280.     const Stop* A;
  281.     const Stop* B;
  282.     int distance;
  283. };
  284.  
  285. struct DistanceHasher {
  286.     std::hash<const void*> hasher;
  287.    
  288.     std::size_t operator()(const std::pair<const Stop*, const Stop*> pair_stops) const noexcept {
  289.         auto hash_1 = static_cast<const void*>(pair_stops.first);
  290.         auto hash_2 = static_cast<const void*>(pair_stops.second);
  291.         return hasher(hash_1) * 17 + hasher(hash_2);
  292.     }  
  293. };
  294.    
  295. typedef  std::unordered_map<std::string_view, Stop*> StopMap;
  296. typedef  std::unordered_map<std::string_view, Bus*> BusMap;
  297. typedef  std::unordered_map<std::pair<const Stop*, const  Stop*>, int, DistanceHasher> DistanceMap;
  298.  
  299. class TransportCatalogue {
  300. public:  
  301.    
  302.     void add_bus(Bus&& bus);
  303.     void add_stop(Stop&& stop);
  304.     void add_distance(const std::vector<Distance>& distances);
  305.    
  306.     Bus* get_bus(std::string_view bus_name);
  307.     Stop* get_stop(std::string_view stop_name);
  308.  
  309.     std::unordered_set<const Bus*> stop_get_uniq_buses(Stop* stop);    
  310.     std::unordered_set<const Stop*> get_uniq_stops(Bus* bus);
  311.     double get_length(Bus* bus);
  312.    
  313.     size_t get_distance_stop(const Stop* start, const Stop* finish);
  314.     size_t get_distance_to_bus(Bus* bus);
  315.    
  316. private:
  317.    
  318.     std::deque<Stop> stops;
  319.     StopMap stopname_to_stop;
  320.    
  321.     std::deque<Bus> buses;
  322.     BusMap busname_to_bus;
  323.    
  324.     DistanceMap distance_to_stop;
  325.    
  326. };
  327.    
  328. }//end namespace transport_catalogue
  329. -----------------------------------------------------------------------
  330. input_reader.cpp
  331. -----------------------------------------------------------------------
  332. #include "input_reader.h"
  333. #include "stat_reader.h"
  334. #include <algorithm>
  335.  
  336. namespace transport_catalogue {
  337. namespace detail {
  338. namespace stop {
  339.    
  340. Stop parse_stop(const std::string& str) {
  341.     auto twopoint_pos = str.find(':');
  342.     auto comma_pos = str.find(',');
  343.     auto entry_length = 5;
  344.     auto distance = 2;
  345.     Stop stop;
  346.  
  347.     stop.name = str.substr(entry_length,
  348.                              twopoint_pos - entry_length);
  349.     stop.latitude = stod(str.substr(twopoint_pos + distance,
  350.                                       comma_pos - twopoint_pos - distance));
  351.     stop.longitude = stod(str.substr(comma_pos + distance));
  352.    
  353.     return stop;
  354. }
  355.    
  356. }//end namespace stop
  357.    
  358. namespace distance {
  359.    
  360. std::vector<Distance> parse_distances(const std::string& str, TransportCatalogue& catalogue) {
  361.     std::vector<Distance> distances;
  362.     auto entry_length = 5;
  363.     auto twopoint_pos = str.find(':');
  364.     auto space = 2;
  365.    
  366.     std::string str_copy = str;
  367.     std::string name = str_copy.substr(entry_length,
  368.                                    twopoint_pos - entry_length);
  369.     str_copy = str_copy.substr(str_copy.find(',') + 1);
  370.     str_copy = str_copy.substr(str_copy.find(',') + space);
  371.  
  372.     while(str_copy.find(',') != std::string::npos){                    
  373.         int distance = stoi(str_copy.substr(0, str_copy.find('m')));
  374.         std::string stop_dist_name = str_copy.substr(str_copy.find('m') + entry_length);
  375.         stop_dist_name = stop_dist_name.substr(0, stop_dist_name.find(','));
  376.         distances.push_back({catalogue.get_stop(name),
  377.                               catalogue.get_stop(stop_dist_name), distance});
  378.         str_copy = str_copy.substr(str_copy.find(',') + space);
  379.     }
  380.     std::string last_name = str_copy.substr(str_copy.find('m') + entry_length);
  381.     int distance = stoi(str_copy.substr(0, str_copy.find('m')));
  382.     distances.push_back({catalogue.get_stop(name), catalogue.get_stop(last_name), distance});
  383.    
  384.     return distances;
  385. }
  386.    
  387. }//end namespace distance
  388.    
  389. namespace bus {
  390.    
  391. Bus parse_bus(std::string_view str, TransportCatalogue& catalogue) {
  392.     auto entry_length = 4;
  393.     auto distance = 2;
  394.     auto twopoint_pos = str.find(':');
  395.     Bus bus;
  396.     bus.name = str.substr(entry_length,
  397.                            twopoint_pos - entry_length);
  398.  
  399.     str = str.substr(twopoint_pos + distance);
  400.  
  401.     auto more_pos = str.find('>');
  402.     if (more_pos == std::string_view::npos) {
  403.         auto tire_pos = str.find('-');
  404.  
  405.         while (tire_pos != std::string_view::npos) {
  406.             bus.stops.push_back(catalogue.get_stop(str.substr(0, tire_pos - 1)));
  407.  
  408.             str = str.substr(tire_pos + distance);
  409.             tire_pos = str.find('-');
  410.         }
  411.  
  412.         bus.stops.push_back(catalogue.get_stop(str.substr(0, tire_pos - 1)));
  413.         size_t size = bus.stops.size() - 1;
  414.  
  415.         for (size_t i = size; i > 0; i--) {
  416.             bus.stops.push_back(bus.stops[i-1]);
  417.         }
  418.  
  419.     } else {
  420.         while (more_pos != std::string_view::npos) {
  421.             bus.stops.push_back(catalogue.get_stop(str.substr(0, more_pos - 1)));
  422.  
  423.             str = str.substr(more_pos + distance);
  424.             more_pos = str.find('>');
  425.         }
  426.  
  427.         bus.stops.push_back(catalogue.get_stop(str.substr(0, more_pos - 1)));
  428.     }
  429.    
  430.     return bus;
  431. }
  432.    
  433. }//end namespace bus
  434.    
  435. void fill_catalogue(std::istream& input, TransportCatalogue& catalogue) {
  436.  
  437.     std::string count;
  438.     std::getline(input, count);
  439.  
  440.     if (count != "") {
  441.         std::string str;
  442.         std::vector<std::string> buses;
  443.         std::vector<std::string> stops;
  444.         int amount = stoi(count);
  445.         auto bus_distance = 3;
  446.  
  447.         for (int i = 0; i < amount; ++i) {
  448.             std::getline(input, str);
  449.  
  450.             if (str != "") {
  451.                 auto space_pos = str.find_first_not_of(' ');
  452.                 str = str.substr(space_pos);
  453.  
  454.                 if (str.substr(0, bus_distance) != "Bus") {
  455.                     stops.push_back(str);
  456.                 } else {
  457.                     buses.push_back(str);
  458.                 }
  459.             }
  460.         }
  461.  
  462.         for (auto stop : stops) {
  463.             catalogue.add_stop(stop::parse_stop(stop));
  464.         }
  465.  
  466.         for (auto stop : stops) {
  467.             catalogue.add_distance(distance::parse_distances(stop, catalogue));
  468.         }
  469.  
  470.         for (auto bus : buses) {
  471.             catalogue.add_bus(bus::parse_bus(bus, catalogue));
  472.         }
  473.     }
  474. }
  475.    
  476. }//end namespace detail
  477. }//end namespace transport_catalogue
  478. -----------------------------------------------------------------------
  479. stat_reader.cpp
  480. -----------------------------------------------------------------------
  481. #include "stat_reader.h"
  482.  
  483. namespace transport_catalogue {
  484. namespace detail {
  485. namespace bus {  
  486.    
  487. void show_terminal(BusQueryResult bus_info, std::ostream& output) {
  488.     if(bus_info.not_found) {
  489.         output << "Bus " << bus_info.name << ": not found" << std::endl;
  490.     }
  491.     else{
  492.         output << "Bus " << bus_info.name << ": "
  493.                << bus_info.stops_on_route << " stops on route, "
  494.                << bus_info.unique_stops << " unique stops, "
  495.                << bus_info.route_length << " route length, "
  496.                << std::setprecision(6) << bus_info.curvature
  497.                << " curvature" << std::endl;
  498.     }
  499. }
  500. BusQueryResult query(TransportCatalogue& catalogue, std::string_view bus_name) {
  501.     BusQueryResult bus_info;
  502.     auto entry = 4;
  503.     bus_name = bus_name.substr(entry);
  504.  
  505.     Bus* bus = catalogue.get_bus(bus_name);
  506.     if (bus != nullptr) {                
  507.         bus_info.name = bus->name;
  508.         bus_info.not_found = false;
  509.         bus_info.stops_on_route = bus->stops.size();
  510.         bus_info.unique_stops = catalogue.get_uniq_stops(bus).size();
  511.         bus_info.route_length = bus->route_length;
  512.         bus_info.curvature = double(catalogue.get_distance_to_bus(bus)
  513.                                     /catalogue.get_length(bus));                    
  514.     } else {  
  515.         bus_info.name = bus_name;
  516.         bus_info.not_found = true;
  517.     }
  518.     return bus_info;
  519. }
  520.    
  521. }//end namespace bus
  522.    
  523. namespace stop {  
  524.    
  525. void show_terminal(const StopQueryResult& stop_info, std::ostream& output) {
  526.     if(stop_info.not_found) {
  527.         output << "Stop " << stop_info.name << ": not found" << std::endl;
  528.     } else {
  529.         if(stop_info.buses_name.size() == 0){
  530.             output << "Stop " << stop_info.name << ": no buses" << std::endl;
  531.         } else {
  532.             output << "Stop " << stop_info.name << ": buses ";
  533.  
  534.             for (std::string_view bus_name : stop_info.buses_name) {
  535.                  output << bus_name;
  536.                  output << " ";
  537.             }
  538.             output << std::endl;
  539.         }
  540.     }
  541. }
  542.    
  543. StopQueryResult query(TransportCatalogue& catalogue, std::string_view stop_name) {
  544.     auto entry = 5;
  545.     stop_name = stop_name.substr(entry);
  546.     std::unordered_set<const Bus*> unique_buses;
  547.  
  548.     StopQueryResult stop_info;
  549.  
  550.     Stop* stop = catalogue.get_stop(stop_name);
  551.  
  552.     if (stop != NULL) {
  553.         stop_info.name = stop->name;
  554.         stop_info.not_found = false;
  555.         unique_buses = catalogue.stop_get_uniq_buses(stop);
  556.        
  557.         if(unique_buses.size() > 0){
  558.             for (const Bus* bus : unique_buses) {
  559.                 stop_info.buses_name.push_back(bus->name);
  560.             }
  561.             std::sort(stop_info.buses_name.begin(), stop_info.buses_name.end());
  562.         }        
  563.     }
  564.     else {    
  565.         stop_info.name = stop_name;
  566.         stop_info.not_found = true;
  567.     }
  568.     return stop_info;
  569. }
  570.    
  571. }//end namespace stop
  572.    
  573. void execute_query(TransportCatalogue& catalogue, std::string_view str) {
  574.     if (str.substr(0, 3) == "Bus") {
  575.         bus::show_terminal(bus::query(catalogue, str), std::cout);
  576.     } else if (str.substr(0, 4) == "Stop") {
  577.         stop::show_terminal(stop::query(catalogue, str), std::cout);
  578.     } else{
  579.         std::cout << "Error query" << std::endl;
  580.     }
  581. }
  582.  
  583. void parse_and_execute_queries(std::istream& input, TransportCatalogue& catalogue) {
  584.     std::string count;
  585.     std::getline(input, count);
  586.    
  587.     std::string str;
  588.     std::vector<std::string> query;
  589.     auto amount = stoi(count);
  590.    
  591.     for (int i = 0; i < amount; ++i) {
  592.         std::getline(input, str);
  593.         query.push_back(str);
  594.     }
  595.    
  596.     for (auto& strr : query) {
  597.         execute_query(catalogue, strr);
  598.     }
  599. }
  600.    
  601. }//end namespace detail
  602. }//end namespace transport_catalogue
Add Comment
Please, Sign In to add comment