W_A_S_A_B_I

hdf45herh

Nov 27th, 2023
296
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 8.31 KB | Source Code | 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) && !complete_parks_.count(car)) {
  82.             now_parked_[car] = Clock::now();
  83.         }
  84.         else if (!now_parked_.count(car) && complete_parks_.count(car)) {
  85.             now_parked_[car] = Clock::now() - complete_parks_.at(car);
  86.             complete_parks_.erase(car);
  87.         }
  88.         else if (now_parked_.count(car)) {
  89.             throw ParkingException();
  90.         }
  91.  
  92.     }
  93.  
  94.     // забрать машину с указанным номером
  95.     void Withdraw(const VehiclePlate& car) {
  96.         if (now_parked_.count(car)) {
  97.             complete_parks_[car] = Clock::now() - now_parked_.at(car);
  98.             now_parked_.erase(car);
  99.         }
  100.         else {
  101.             throw ParkingException();
  102.         }
  103.        
  104.     }
  105.  
  106.     // получить счёт за конкретный автомобиль
  107.     int64_t GetCurrentBill(const VehiclePlate& car) const {
  108.         Duration in_parking;
  109.         if (now_parked_.count(car)) {
  110.             in_parking = Clock::now() - now_parked_.at(car);
  111.         }
  112.         else if (complete_parks_.count(car)) {
  113.             in_parking = complete_parks_.at(car);
  114.         }
  115.         else {
  116.             return 0;
  117.         }
  118.  
  119.         int64_t seconds_on_parking = chrono::duration_cast<chrono::seconds>(in_parking).count();
  120.         int64_t summary_parking_cost = seconds_on_parking * cost_per_second_;
  121.  
  122.         return summary_parking_cost;
  123.     }
  124.  
  125.     // завершить расчётный период
  126.     // те машины, которые находятся на парковке на данный момент, должны
  127.     // остаться на парковке, но отсчёт времени для них начинается с нуля
  128.     unordered_map<VehiclePlate, int64_t, VehiclePlateHasher> EndPeriodAndGetBills() {
  129.         // место для вашей реализации
  130.         unordered_map<VehiclePlate, int64_t, VehiclePlateHasher> result;
  131.         if (!now_parked_.empty()) {
  132.             for (auto& car : now_parked_) {
  133.                 if (car.second < Clock::now()) {
  134.                     result[car.first] = GetCurrentBill(car.first);
  135.                     car.second = Clock::now();
  136.                 }
  137.             }
  138.         }
  139.  
  140.         if (!complete_parks_.empty()) {
  141.             for (auto& car : complete_parks_) {
  142.                 if (car.second.count() > 0) {
  143.                     result[car.first] = GetCurrentBill(car.first);
  144.                     car.second = 0s;
  145.                 }
  146.             }
  147.         }
  148.         complete_parks_.clear();
  149.        
  150.         return result;
  151.     }
  152.  
  153.     // не меняйте этот метод
  154.     auto& GetNowParked() const {
  155.         return now_parked_;
  156.     }
  157.  
  158.     // не меняйте этот метод
  159.     auto& GetCompleteParks() const {
  160.         return complete_parks_;
  161.     }
  162.  
  163. private:
  164.     int cost_per_second_;
  165.     unordered_map<VehiclePlate, TimePoint, VehiclePlateHasher> now_parked_;
  166.     unordered_map<VehiclePlate, Duration, VehiclePlateHasher> complete_parks_;
  167.  
  168. };
  169.  
  170. // эти часы удобно использовать для тестирования
  171. // они покажут столько времени, сколько вы задали явно
  172. class TestClock {
  173. public:
  174.     using time_point = chrono::system_clock::time_point;
  175.     using duration = chrono::system_clock::duration;
  176.  
  177.     static void SetNow(int seconds) {
  178.         current_time_ = seconds;
  179.     }
  180.  
  181.     static time_point now() {
  182.         return start_point_ + chrono::seconds(current_time_);
  183.     }
  184.  
  185. private:
  186.     inline static time_point start_point_ = chrono::system_clock::now();
  187.     inline static int current_time_ = 0;
  188. };
  189.  
  190. int main() {
  191.     Parking<TestClock> parking(10);
  192.  
  193.     TestClock::SetNow(10);
  194.     parking.Park({ 'A', 'A', 111, 'A', 99 });
  195.  
  196.     TestClock::SetNow(20);
  197.     parking.Withdraw({ 'A', 'A', 111, 'A', 99 });
  198.     parking.Park({ 'B', 'B', 222, 'B', 99 });
  199.  
  200.     TestClock::SetNow(40);
  201.     assert(parking.GetCurrentBill({ 'A', 'A', 111, 'A', 99 }) == 100);
  202.     assert(parking.GetCurrentBill({ 'B', 'B', 222, 'B', 99 }) == 200);
  203.     parking.Park({ 'A', 'A', 111, 'A', 99 });
  204.  
  205.     TestClock::SetNow(50);
  206.     assert(parking.GetCurrentBill({ 'A', 'A', 111, 'A', 99 }) == 200);
  207.     assert(parking.GetCurrentBill({ 'B', 'B', 222, 'B', 99 }) == 300);
  208.     assert(parking.GetCurrentBill({ 'C', 'C', 333, 'C', 99 }) == 0);
  209.     parking.Withdraw({ 'B', 'B', 222, 'B', 99 });
  210.  
  211.     TestClock::SetNow(70);
  212.     {
  213.         // проверим счёт
  214.         auto bill = parking.EndPeriodAndGetBills();
  215.  
  216.         // так как внутри макроса используется запятая,
  217.         // нужно заключить его аргумент в дополнительные скобки
  218.         assert((bill
  219.             == unordered_map<VehiclePlate, int64_t, VehiclePlateHasher>{
  220.                 { {'A', 'A', 111, 'A', 99}, 400},
  221.                 { {'B', 'B', 222, 'B', 99}, 300 },
  222.         }));
  223.     }
  224.  
  225.     TestClock::SetNow(80);
  226.     {
  227.         // проверим счёт
  228.         auto bill = parking.EndPeriodAndGetBills();
  229.  
  230.         // так как внутри макроса используется запятая,
  231.         // нужно заключить его аргумент в дополнительные скобки
  232.         assert((bill
  233.             == unordered_map<VehiclePlate, int64_t, VehiclePlateHasher>{
  234.                 { {'A', 'A', 111, 'A', 99}, 100},
  235.         }));
  236.     }
  237.  
  238.     try {
  239.         parking.Park({ 'A', 'A', 111, 'A', 99 });
  240.         assert(false);
  241.     }
  242.     catch (ParkingException) {
  243.     }
  244.  
  245.     try {
  246.         parking.Withdraw({ 'B', 'B', 222, 'B', 99 });
  247.         assert(false);
  248.     }
  249.     catch (ParkingException) {
  250.     }
  251.  
  252.     cout << "Success!"s << endl;
  253. }
Add Comment
Please, Sign In to add comment