Advertisement
giGii

парковка с поддержкой времени

Jan 20th, 2023 (edited)
114
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 8.22 KB | None | 0 0
  1. #include <array>
  2. #include <cassert>
  3. #include <chrono>
  4. #include <iomanip>
  5. #include <iostream>
  6. #include <sstream>
  7. #include <string>
  8. #include <tuple>
  9. #include <unordered_map>
  10. #include <vector>
  11.  
  12. using namespace std;
  13.  
  14. class VehiclePlate {
  15. private:
  16.     auto AsTuple() const {
  17.         return tie(letters_, digits_, region_);
  18.     }
  19.  
  20. public:
  21.     bool operator==(const VehiclePlate& other) const {
  22.         return AsTuple() == other.AsTuple();
  23.     }
  24.  
  25.     VehiclePlate(char l0, char l1, int digits, char l2, int region)
  26.         : letters_{l0, l1, l2}
  27.         , digits_(digits)
  28.         , region_(region) {
  29.     }
  30.  
  31.     string ToString() const {
  32.         ostringstream out;
  33.         out << letters_[0] << letters_[1];
  34.  
  35.         // чтобы дополнить цифровую часть номера слева нулями
  36.         // до трёх цифр, используем подобные манипуляторы:
  37.         // setfill задаёт символ для заполнения,
  38.         // right задаёт выравнивание по правому краю,
  39.         // setw задаёт минимальное желаемое количество знаков
  40.         out << setfill('0') << right << setw(3) << digits_;
  41.         out << letters_[2] << setw(2) << region_;
  42.  
  43.         return out.str();
  44.     }
  45.  
  46. private:
  47.     array<char, 3> letters_;
  48.     int digits_;
  49.     int region_;
  50. };
  51.  
  52. ostream& operator<<(ostream& out, VehiclePlate plate) {
  53.     out << plate.ToString();
  54.     return out;
  55. }
  56.  
  57. // возьмите реализацию хешера из прошлого задания
  58. class VehiclePlateHasher {
  59. public:
  60.     size_t operator()(const VehiclePlate& plate) const {
  61.         return hash<string>()(plate.ToString());
  62.     }
  63. };
  64.  
  65. // выбросьте это исключение в случае ошибки парковки
  66. struct ParkingException {};
  67.  
  68. template <typename Clock>
  69. class Parking {
  70.     // при обращении к типу внутри шаблонного параметра мы обязаны использовать
  71.     // typename; чтобы этого избежать, объявим псевдонимы для нужных типов
  72.     using Duration = typename Clock::duration;
  73.     using TimePoint = typename Clock::time_point;
  74.  
  75. public:
  76.     Parking(int cost_per_second) : cost_per_second_(cost_per_second) {}
  77.  
  78.     // запарковать машину с указанным номером
  79.     void Park(VehiclePlate car) {
  80.         // место для вашей реализации
  81.         if (now_parked_.count(car)) {
  82.             throw ParkingException;
  83.         }
  84.  
  85.         now_parked_[car] = "сейчас" // запарковали машину
  86.     }
  87.  
  88.     // забрать машину с указанным номером
  89.     void Withdraw(const VehiclePlate& car) {
  90.         // место для вашей реализации
  91.         if (!now_parked_.count(car)) {
  92.             throw ParkingException;
  93.         }
  94.  
  95.         complete_parks_[car] += "сейчас" - now_parked_.at(car); // накопили машине секунды
  96.         now_parked_.erase(car); // "забрали" машину с парковки
  97.     }
  98.  
  99.     // получить счёт за конкретный автомобиль
  100.     int64_t GetCurrentBill(const VehiclePlate& car) const {
  101.         // место для вашей реализации
  102.         bool isCarInParking = now_parked_.count(car);
  103.         bool HaveCarDebt = complete_parks_.count(car);
  104.  
  105.         Duration total;
  106.  
  107.         if (!isCarInParking && !HaveCarDebt) { // машины нет в системе
  108.             return 0;
  109.         }
  110.  
  111.         if (isCarInParking) { // если машина на парковке, вписать ей текущий долг
  112.             total += "сейчас" - now_parked_.at(car);
  113.        
  114.         if (HaveCarDebt) { // если машина имеет сформированный долг, вписать и его
  115.             total += complete_parks_.at(car);
  116.         }
  117.  
  118.         return chrono::duration_cast<chrono::seconds>(total).count() * cost_per_second_;
  119.     }
  120.  
  121.     // завершить расчётный период
  122.     // те машины, которые находятся на парковке на данный момент, должны
  123.     // остаться на парковке, но отсчёт времени для них начинается с нуля
  124.     unordered_map<VehiclePlate, int64_t, VehiclePlateHasher> EndPeriodAndGetBills() {
  125.         // место для вашей реализации
  126.         // сколько машины "настояли" -- записать в complete_parks_
  127.         unordered_map<VehiclePlate, int64_t, VehiclePlateHasher> debts;
  128.  
  129.         for (const auto& [car, time_start] : now_parked_) {
  130.             complete_parks_[car] += "сейчас" - time_start;
  131.             time_start = 0;
  132.  
  133.             debts[car] = chrono::duration_cast<chrono::seconds>(complete_parks_[car]).count() * cost_per_second_;
  134.         }
  135.  
  136.         return debts;
  137.     }
  138.  
  139.     // не меняйте этот метод
  140.     auto& GetNowParked() const {
  141.         return now_parked_;
  142.     }
  143.  
  144.     // не меняйте этот метод
  145.     auto& GetCompleteParks() const {
  146.         return complete_parks_;
  147.     }
  148.  
  149. private:
  150.     int cost_per_second_;
  151.     unordered_map<VehiclePlate, TimePoint, VehiclePlateHasher> now_parked_;
  152.     unordered_map<VehiclePlate, Duration, VehiclePlateHasher> complete_parks_;
  153. };
  154.  
  155. // эти часы удобно использовать для тестирования
  156. // они покажут столько времени, сколько вы задали явно
  157. class TestClock {
  158. public:
  159.     using time_point = chrono::system_clock::time_point;
  160.     using duration = chrono::system_clock::duration;
  161.  
  162.     static void SetNow(int seconds) {
  163.         current_time_ = seconds;
  164.     }
  165.  
  166.     static time_point now() {
  167.         return start_point_ + chrono::seconds(current_time_);
  168.     }
  169.  
  170. private:
  171.     inline static time_point start_point_ = chrono::system_clock::now();
  172.     inline static int current_time_ = 0;
  173. };
  174.  
  175. int main() {
  176.     Parking<TestClock> parking(10);
  177.  
  178.     TestClock::SetNow(10);
  179.     parking.Park({'A', 'A', 111, 'A', 99});
  180.  
  181.     TestClock::SetNow(20);
  182.     parking.Withdraw({'A', 'A', 111, 'A', 99});
  183.     parking.Park({'B', 'B', 222, 'B', 99});
  184.  
  185.     TestClock::SetNow(40);
  186.     assert(parking.GetCurrentBill({'A', 'A', 111, 'A', 99}) == 100);
  187.     assert(parking.GetCurrentBill({'B', 'B', 222, 'B', 99}) == 200);
  188.     parking.Park({'A', 'A', 111, 'A', 99});
  189.  
  190.     TestClock::SetNow(50);
  191.     assert(parking.GetCurrentBill({'A', 'A', 111, 'A', 99}) == 200);
  192.     assert(parking.GetCurrentBill({'B', 'B', 222, 'B', 99}) == 300);
  193.     assert(parking.GetCurrentBill({'C', 'C', 333, 'C', 99}) == 0);
  194.     parking.Withdraw({'B', 'B', 222, 'B', 99});
  195.  
  196.     TestClock::SetNow(70);
  197.     {
  198.         // проверим счёт
  199.         auto bill = parking.EndPeriodAndGetBills();
  200.  
  201.         // так как внутри макроса используется запятая,
  202.         // нужно заключить его аргумент в дополнительные скобки
  203.         assert((bill
  204.                 == unordered_map<VehiclePlate, int64_t, VehiclePlateHasher>{
  205.                    {{'A', 'A', 111, 'A', 99}, 400},
  206.                    {{'B', 'B', 222, 'B', 99}, 300},
  207.                }));
  208.     }
  209.  
  210.     TestClock::SetNow(80);
  211.     {
  212.         // проверим счёт
  213.         auto bill = parking.EndPeriodAndGetBills();
  214.  
  215.         // так как внутри макроса используется запятая,
  216.         // нужно заключить его аргумент в дополнительные скобки
  217.         assert((bill
  218.                 == unordered_map<VehiclePlate, int64_t, VehiclePlateHasher>{
  219.                    {{'A', 'A', 111, 'A', 99}, 100},
  220.                }));
  221.     }
  222.  
  223.     try {
  224.         parking.Park({'A', 'A', 111, 'A', 99});
  225.         assert(false);
  226.     }
  227.     catch (ParkingException) {
  228.     }
  229.  
  230.     try {
  231.         parking.Withdraw({'B', 'B', 222, 'B', 99});
  232.         assert(false);
  233.     }
  234.     catch (ParkingException) {
  235.     }
  236.  
  237.     cout << "Success!"s << endl;
  238. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement