shushus

Спринт 10. Устройство unordered_map и unordered_set. Задание 2.

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