Advertisement
Guest User

Untitled

a guest
Oct 17th, 2019
92
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 12.91 KB | None | 0 0
  1. #include <iostream>
  2. #include <string>
  3. #include <set>
  4. #include <vector>
  5. #include <regex>
  6. #include <cmath>
  7. #include <cstdio>
  8. #include <cstdlib>
  9. #include <map>
  10. #include <unordered_map>
  11. #include <climits>
  12. #include <unordered_set>
  13.  
  14. using ULL = unsigned long long;
  15. const ULL INF = 1e18 + 10;
  16.  
  17. // makra do odpowiadajace typom zapytania z wejscia
  18. using BusRoute = std::pair<std::string, std::vector<std::pair<int, std::string>>>;
  19. using Ticket = std::tuple<std::string, ULL, int>;
  20. using TicketRequest = std::pair<std::vector<std::string>, std::vector<std::string>>;
  21.  
  22. int timeToMin(std::string time) {
  23.     std::string hours;
  24.     std::string mins;
  25.     hours += time[0];
  26.     const std::string semi = ":";
  27.     const std::string zero = "0";
  28.     if(time[2] == semi[0]) {
  29.         hours += time[1];
  30.         mins += time[3];
  31.         mins += time[4];
  32.     }
  33.     else {
  34.         mins += time[2];
  35.         mins += time[3];
  36.     }
  37.  
  38.     return std::stoi(hours) * 60 + std::stoi(mins);
  39. }
  40.  
  41. // funkcje parsujace linijki na zmienne (lub false gdy linijki sa niepoprawne)
  42. std::pair<bool, BusRoute> parseBusRouteCommand(const std::string& command,
  43.                                                std::unordered_set<std::string>& lineNumSet,
  44.                                                std::unordered_map<std::string, std::unordered_set<std::string>>& busLines) {
  45.  
  46.     std::pair<bool, BusRoute> busRoute;
  47.  
  48.     std::string lineNum = "";
  49.     int x = 0;
  50.     const std::string zero = "0";
  51.  
  52.     while(command[x] == zero[0]) {
  53.         x++;
  54.     }
  55.  
  56.     while(std::isdigit(command[x])) {
  57.         lineNum += command[x];
  58.         x++;
  59.     }
  60.  
  61.     if(lineNum == "") {
  62.         lineNum = "0";
  63.     }
  64.  
  65.     if(lineNumSet.find(lineNum) != lineNumSet.end()) {
  66.         return {false, {}};
  67.     }
  68.     else {
  69.         busRoute.second.first = lineNum;
  70.     }
  71.  
  72.     const std::regex reg("(5:5[5-9]|([6-9]|1[0-9]|20):\\d\\d|21:1[0-9]|21:2[0-1])|([a-zA-Z]|_|\\^)+");
  73.     auto itBegin = std::sregex_iterator(command.begin(), command.end(), reg);
  74.     auto itEnd = std::sregex_iterator();
  75.     const std::regex stopsReg("([a-zA-Z]|_|\\^)+");
  76.     const std::regex timeReg("\\d+:\\d\\d");
  77.     std::unordered_set<std::string> stopsSet;
  78.     std::vector<std::string> stops;
  79.     std::vector<int> stopTimes;
  80.     int mins;
  81.     int lastMins = -1;
  82.  
  83.     for (std::sregex_iterator i = itBegin; i != itEnd; ++i) {
  84.         std::smatch match = *i;
  85.         std::string matchStr = match.str();
  86.         if(std::regex_match(matchStr, stopsReg)) {
  87.             if(stopsSet.find(matchStr) != stopsSet.end()) {
  88.                 return {false, {}};
  89.             }
  90.             else {
  91.                 stopsSet.insert(matchStr);
  92.                 stops.push_back(matchStr);
  93.             }
  94.         }
  95.         else if(std::regex_match(matchStr, timeReg)) {
  96.             mins = timeToMin(matchStr);
  97.             if(lastMins >= mins) {
  98.                 return {false, {}};
  99.             }
  100.             stopTimes.push_back(mins);
  101.             lastMins = mins;
  102.         }
  103.     }
  104.  
  105.     lineNumSet.insert(lineNum);
  106.  
  107.     std::pair<int, std::string> p;
  108.     for(size_t i = 0; i < stopTimes.size(); i++) {
  109.         p.first = stopTimes[i];
  110.         p.second = stops[i];
  111.         busRoute.second.second.push_back(p);
  112.     }
  113.  
  114.     for(const auto& pp : busRoute.second.second) {
  115.         busLines[busRoute.second.first].insert(pp.second);
  116.     }
  117.  
  118.     busRoute.first = true;
  119.     return busRoute;
  120. }
  121.  
  122. std::pair<bool, Ticket> parseNewTicketCommand(const std::string& command,
  123.                                               std::unordered_set<std::string>& ticketNameSet) {
  124.  
  125.     std::pair<bool, Ticket> ticket;
  126.  
  127.     std::string ticketName;
  128.  
  129.     int x = 0;
  130.  
  131.     while(!std::isdigit(command[x+1])) {
  132.         ticketName += command[x];
  133.         x += 1;
  134.     }
  135.  
  136.     if(ticketNameSet.find(ticketName) != ticketNameSet.end()) {
  137.         return {false, {}};
  138.     }
  139.  
  140.     const std::regex reg("\\d+\\.\\d\\d|[1-9][0-9]*");
  141.     auto itBegin = std::sregex_iterator(command.begin(), command.end(), reg);
  142.     auto itEnd = std::sregex_iterator();
  143.     const std::regex priceReg("\\d+\\.\\d\\d");
  144.     const std::regex durReg("[1-9][0-9]*");
  145.     ULL ticketPrice;
  146.     int ticketDur;
  147.  
  148.     for (std::sregex_iterator i = itBegin; i != itEnd; ++i) {
  149.         std::smatch match = *i;
  150.         std::string matchStr = match.str();
  151.         if(std::regex_match(matchStr, priceReg)) {
  152.             matchStr.erase(matchStr.length()-3, 1);
  153.             int x = 0;
  154.             const std::string zero = "0";
  155.  
  156.             while (matchStr[x] == zero[0]) {
  157.                 x++;
  158.             }
  159.  
  160.             matchStr.erase(0, x);
  161.  
  162.             if(matchStr == "") {
  163.                 matchStr = "0";
  164.             }
  165.  
  166.             if(18 < matchStr.length()) {
  167.                 return {false, {}};
  168.             }
  169.             else {
  170.                 ticketPrice = std::stoull(matchStr);
  171.             }
  172.         }
  173.         else if(std::regex_match(matchStr, durReg)) {
  174.             if(std::stoi(matchStr) > 60*24) {
  175.                 return {false, {}};
  176.             }
  177.             else {
  178.                 ticketDur = std::stoi(matchStr);
  179.             }
  180.         }
  181.     }
  182.  
  183.     ticketNameSet.insert(ticketName);
  184.     return {true, {ticketName, ticketPrice, ticketDur}};
  185. }
  186.  
  187. std::pair<bool, TicketRequest> parseTicketRequestCommand(const std::string& command,
  188.                                                          const std::unordered_set<std::string>& lineNumSet,
  189.                                                          std::unordered_map<std::string, std::unordered_set<std::string>>& busLines) {
  190.  
  191.     const std::regex reg("\\d+|([a-zA-Z]|_|\\^)+");
  192.     auto itBegin = std::sregex_iterator(command.begin(), command.end(), reg);
  193.     auto itEnd = std::sregex_iterator();
  194.     const std::regex lineNumReg("\\d+");
  195.     const std::regex stopNameReg("([a-zA-Z]|_|\\^)+");
  196.     std::vector<std::string> stops;
  197.     std::vector<std::string> lineNumbers;
  198.     const std::string zero = "0";
  199.  
  200.     for (std::sregex_iterator i = itBegin; i != itEnd; ++i) {
  201.         std::smatch match = *i;
  202.         std::string matchStr = match.str();
  203.  
  204.         if(std::regex_match(matchStr, lineNumReg)) {
  205.             int x = 0;
  206.             std::string zero = "0";
  207.             std::string dot = ".";
  208.  
  209.             while (matchStr[x] == zero[0]) {
  210.                 x++;
  211.             }
  212.  
  213.             matchStr.erase(0, x);
  214.  
  215.             if(matchStr == "") {
  216.                 matchStr = "0";
  217.             }
  218.  
  219.             if(lineNumSet.find(matchStr) == lineNumSet.end()) {
  220.                 return {false, {}};
  221.             }
  222.             else {
  223.                 lineNumbers.push_back(matchStr);
  224.             }
  225.         }
  226.         else if(std::regex_match(matchStr, stopNameReg)) {
  227.             stops.push_back(matchStr);
  228.         }
  229.     }
  230.  
  231.     for(size_t i = 0; i < lineNumbers.size(); i++) {
  232.         if(busLines[lineNumbers[i]].find(stops[i]) == busLines[lineNumbers[i]].end()) {
  233.             return {false, {}};
  234.         }
  235.     }
  236.  
  237.     if(busLines[lineNumbers[lineNumbers.size()-1]].find(stops[stops.size()-1]) == busLines[lineNumbers[lineNumbers.size()-1]].end()) {
  238.         return {false, {}};
  239.     }
  240.  
  241.     for(size_t i = 1; i < stops.size(); i++) {
  242.         if(stops[i] == stops[i - 1]) {
  243.             return {false, {}};
  244.         }
  245.     }
  246.  
  247.  
  248.     return {true, {stops, lineNumbers}};
  249. }
  250.  
  251. // funkcje wykonujace odpowiednie linijki z wejscia
  252. void executeBusRoute(const BusRoute& busRoute,
  253.                      std::map<std::string, std::map<std::string, int>>& busStops) {
  254.  
  255.     auto name = busRoute.first;
  256.     auto timetable = busRoute.second;
  257.    
  258.     for(const auto& p : timetable) {
  259.         auto time = p.first;
  260.         auto busStop = p.second;
  261.  
  262.         busStops[busStop][name] = time;
  263.     }
  264. }
  265.  
  266. void executeNewTicket(const Ticket& ticket, std::vector<Ticket>& tickets) {
  267.     tickets.push_back(ticket);
  268. }
  269.  
  270. std::string executeTicketRequest(const TicketRequest& ticketRequest,
  271.                                  std::map<std::string, std::map<std::string, int>>& busStops,
  272.                                  std::vector<Ticket>& tickets,
  273.                                  int& numberOfTickets) {
  274.  
  275.     auto stops = ticketRequest.first;
  276.     auto routes = ticketRequest.second;
  277.  
  278.     for(size_t i = 1; i < routes.size(); i++) {
  279.         auto currStop = stops[i];
  280.         auto prevRoute = routes[i - 1];
  281.         auto nextRoute = routes[i];
  282.        
  283.         int prevTime = busStops[currStop][prevRoute];
  284.         int nextTime = busStops[currStop][nextRoute];
  285.        
  286.         if(prevTime < nextTime) {
  287.             return ":-( " + currStop;
  288.         }
  289.         else if(prevTime > nextTime) {
  290.             return "";
  291.         }
  292.     }
  293.  
  294.     if(routes.size() == 1) {
  295.         if(busStops[stops.back()][routes.back()] < busStops[stops[0]][routes[0]]) {
  296.             return "";
  297.         }
  298.     }
  299.  
  300.  
  301.     int time = busStops[stops.back()][routes.back()] - busStops[stops[0]][routes[0]] + 1;
  302.  
  303.     std::vector<Ticket> bestTickets;
  304.     ULL lowestPrice = INF;
  305.  
  306.     for(size_t i = 0; i < tickets.size(); i++) {
  307.         for(size_t j = i; j <= tickets.size(); j++) {
  308.             for(size_t k = j; k <= tickets.size(); k++) {
  309.  
  310.                 std::vector<Ticket> curr;
  311.  
  312.                 curr.push_back(tickets[i]);
  313.                 if(j != tickets.size())
  314.                     curr.push_back(tickets[j]);
  315.                 if(k != tickets.size())
  316.                     curr.push_back(tickets[k]);
  317.  
  318.                 int currTime = 0;
  319.                 for(const auto& t : curr)
  320.                     currTime += std::get<2>(t);
  321.  
  322.                 if(currTime >= time) {
  323.                     ULL currPrice = 0;
  324.                     for(const auto& t : curr)
  325.                         currPrice += std::get<1>(t);
  326.  
  327.                     if(currPrice < lowestPrice) {
  328.                         lowestPrice = currPrice;
  329.                         bestTickets = curr;
  330.                     }
  331.                 }
  332.             }
  333.         }
  334.     }
  335.  
  336.     if(bestTickets.empty()) {
  337.         return ":-|";
  338.     }
  339.  
  340.     std::string ret = "!";
  341.     for(auto t : bestTickets) {
  342.         ret.append(" " + std::get<0>(t) + ";");
  343.     }
  344.     ret.pop_back();
  345.  
  346.     numberOfTickets += (int)bestTickets.size();
  347.  
  348.     return ret;
  349. }
  350.  
  351. int main() {
  352.  
  353.     // regexy do wstepnego sprawdzenia linijki
  354.     const std::regex regBusRouteCommand("\\d+( (5:5[5-9]|([6-9]|1[0-9]|20):[0-5]\\d|21:1[0-9]|21:2[0-1]) ([a-zA-Z]|_|\\^)+)+");
  355.     const std::regex regTicketCommand("([a-zA-Z]| )+ \\d+\\.\\d\\d [1-9][0-9]*");
  356.     const std::regex regTicketRequestCommand("\\?( ([a-zA-Z]|_|\\^)+ \\d+)+ ([a-zA-Z]|\\^|_)+");
  357.  
  358.     // struktury do parsowania wejscia
  359.     std::unordered_set<std::string> ticketNameSet;
  360.     std::unordered_set<std::string> lineNumSet;
  361.     std::unordered_map<std::string, std::unordered_set<std::string>> busLines;
  362.  
  363.     // struktury do odpowiedzi na zapytania
  364.     std::map<std::string, std::map<std::string, int>> busStops;
  365.     std::vector<Ticket> tickets;
  366.  
  367.  
  368.     int lineId = 0;
  369.     std::string line;
  370.     int numberOfTickets = 0;
  371.  
  372.     // wczytywanie linijka po linijce
  373.     while(getline(std::cin, line)) {
  374.    
  375.         lineId++;
  376.  
  377.         if(line.empty()) {
  378.             continue;
  379.         }
  380.  
  381.         bool badLine = false;
  382.  
  383.         if(isdigit(line[0]) || line[0] == '_' || line[0] == '^') {
  384.             if(!regex_match(line, regBusRouteCommand)) {
  385.                 badLine = true;
  386.             }
  387.             else {
  388.                 auto p = parseBusRouteCommand(line, lineNumSet, busLines);
  389.                 if (p.first)
  390.                     executeBusRoute(p.second, busStops);
  391.                 else
  392.                     badLine = true;
  393.             }
  394.         }
  395.         else if(isalpha(line[0]) || isspace(line[0])) {
  396.             if(!regex_match(line, regTicketCommand)) {
  397.                 badLine = true;
  398.             }
  399.             else {
  400.                 auto p = parseNewTicketCommand(line, ticketNameSet);
  401.                 if(p.first)
  402.                     executeNewTicket(p.second, tickets);
  403.                 else
  404.                     badLine = true;
  405.             }
  406.         }
  407.         else if(line[0] == '?') {
  408.             if(!regex_match(line, regTicketRequestCommand)) {
  409.                 badLine = true;
  410.             }
  411.             else {
  412.                 auto p = parseTicketRequestCommand(line, lineNumSet, busLines);
  413.                 if(p.first) {
  414.                     std::string ticketRequestOutput = executeTicketRequest(p.second, busStops, tickets, numberOfTickets);
  415.                     if(ticketRequestOutput == "")
  416.                         badLine = true;
  417.                     else
  418.                         std::cout << ticketRequestOutput << "\n";
  419.                 }
  420.                 else
  421.                     badLine = true;
  422.             }
  423.         }
  424.         else {
  425.             badLine = true;
  426.         }
  427.  
  428.         if(badLine) {
  429.             std::cerr << "Error in line " << lineId << ": " << line << "\n";
  430.         }
  431.     }
  432.  
  433.     std::cout << numberOfTickets << "\n";
  434.  
  435.     return 0;
  436. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement