35657

Untitled

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