AlexSSH

Untitled

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