Advertisement
kutuzzzov

Урок 6

Feb 20th, 2023
1,298
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 6.32 KB | None | 0 0
  1. // main.cpp
  2.  
  3. #include "log_duration.h"
  4.  
  5. #include <algorithm>
  6. #include <array>
  7. #include <iomanip>
  8. #include <iostream>
  9. #include <iterator>
  10. #include <random>
  11. #include <set>
  12. #include <string>
  13. #include <sstream>
  14. #include <unordered_set>
  15.  
  16. using namespace std;
  17.  
  18. class VehiclePlate {
  19. private:
  20.     auto AsTuple() const {
  21.         return tie(letters_, digits_, region_);
  22.     }
  23.  
  24. public:
  25.     bool operator==(const VehiclePlate& other) const {
  26.         return AsTuple() == other.AsTuple();
  27.     }
  28.  
  29.     bool operator<(const VehiclePlate& other) const {
  30.         return AsTuple() < other.AsTuple();
  31.     }
  32.  
  33.     VehiclePlate(char l0, char l1, int digits, char l2, int region)
  34.         : letters_{l0, l1, l2}
  35.         , digits_(digits)
  36.         , region_(region) {
  37.     }
  38.  
  39.     string ToString() const {
  40.         ostringstream out;
  41.         out << letters_[0] << letters_[1];
  42.         out << setfill('0') << right << setw(3) << digits_;
  43.         out << letters_[2] << setw(2) << region_;
  44.  
  45.         return out.str();
  46.     }
  47.  
  48.     const array<char, 3>& GetLetters() const {
  49.         return letters_;
  50.     }
  51.  
  52.     int GetDigits() const {
  53.         return digits_;
  54.     }
  55.  
  56.     int GetRegion() const {
  57.         return region_;
  58.     }
  59.  
  60. private:
  61.     array<char, 3> letters_;
  62.     int digits_;
  63.     int region_;
  64. };
  65.  
  66. struct PlateHasherTrivial {
  67.     size_t operator()(const VehiclePlate& plate) const {
  68.         return static_cast<size_t>(plate.GetDigits());
  69.     }
  70. };
  71.  
  72. struct PlateHasherRegion {
  73.     size_t operator()(const VehiclePlate& plate) const {
  74.         return static_cast<size_t>(plate.GetDigits() + plate.GetRegion() * 1000);
  75.     }
  76. };
  77.  
  78. struct PlateHasherString {
  79.     size_t operator()(const VehiclePlate& plate) const {
  80.         return hasher(plate.ToString());
  81.     }
  82.  
  83.     hash<string> hasher;
  84. };
  85.  
  86. struct PlateHasherAll {
  87.     // реализуйте собственный хешер, который будет
  88.     // эффективнее и лучше всех остальных
  89.     size_t operator()(const VehiclePlate& plate) const {
  90.         auto letters = plate.GetLetters();
  91.         return static_cast<size_t>(plate.GetRegion() * 1000000 + ((letters[2] - 'A') + (letters[1] - 'A') + (letters[0] - 'A')) * 1000 + plate.GetDigits());
  92.     }
  93. };
  94.  
  95. ostream& operator<<(ostream& out, VehiclePlate plate) {
  96.     out << plate.ToString();
  97.     return out;
  98. }
  99.  
  100. class PlateGenerator {
  101.     char GenerateChar() {
  102.         uniform_int_distribution<short> char_gen{0, static_cast<short>(possible_chars_.size() - 1)};
  103.         return possible_chars_[char_gen(engine_)];
  104.     }
  105.  
  106.     int GenerateNumber() {
  107.         uniform_int_distribution<short> num_gen{0, 999};
  108.         return num_gen(engine_);
  109.     }
  110.  
  111.     int GenerateRegion() {
  112.         uniform_int_distribution<short> region_gen{0, static_cast<short>(possible_regions_.size() - 1)};
  113.         return possible_regions_[region_gen(engine_)];
  114.     }
  115.  
  116. public:
  117.     VehiclePlate Generate() {
  118.         return VehiclePlate(GenerateChar(), GenerateChar(), GenerateNumber(), GenerateChar(), GenerateRegion());
  119.     }
  120.  
  121. private:
  122.     mt19937 engine_;
  123.  
  124.     // допустимые значения сохраним в static переменных
  125.     // они объявлены inline, чтобы их определение не надо было выносить вне класса
  126.     inline static array possible_regions_
  127.         = {1,  2,  102, 3,   4,   5,   6,   7,   8,  9,   10,  11,  12, 13,  113, 14,  15, 16,  116, 17, 18,
  128.            19, 20, 21,  121, 22,  23,  93,  123, 24, 84,  88,  124, 25, 125, 26,  27,  28, 29,  30,  31, 32,
  129.            33, 34, 35,  36,  136, 37,  38,  85,  39, 91,  40,  41,  82, 42,  142, 43,  44, 45,  46,  47, 48,
  130.            49, 50, 90,  150, 190, 51,  52,  152, 53, 54,  154, 55,  56, 57,  58,  59,  81, 159, 60,  61, 161,
  131.            62, 63, 163, 64,  164, 65,  66,  96,  67, 68,  69,  70,  71, 72,  73,  173, 74, 174, 75,  80, 76,
  132.            77, 97, 99,  177, 199, 197, 777, 78,  98, 178, 79,  83,  86, 87,  89,  94,  95};
  133.  
  134.     // постфикс s у литерала тут недопустим, он приведёт к неопределённому поведению
  135.     inline static string_view possible_chars_ = "ABCEHKMNOPTXY"sv;
  136. };
  137.  
  138. int main() {
  139.     static const int N = 1'000'000;
  140.  
  141.     PlateGenerator generator;
  142.     vector<VehiclePlate> fill_vector;
  143.     vector<VehiclePlate> find_vector;
  144.  
  145.     generate_n(back_inserter(fill_vector), N, [&]() {
  146.         return generator.Generate();
  147.     });
  148.     generate_n(back_inserter(find_vector), N, [&]() {
  149.         return generator.Generate();
  150.     });
  151.  
  152.     int found;
  153.     {
  154.         LOG_DURATION("unordered_set");
  155.         unordered_set<VehiclePlate, PlateHasherAll> container;
  156.         for (auto& p : fill_vector) {
  157.             container.insert(p);
  158.         }
  159.         found = count_if(find_vector.begin(), find_vector.end(), [&](const VehiclePlate& plate) {
  160.             return container.count(plate) > 0;
  161.         });
  162.     }
  163.     cout << "Found matches (1): "s << found << endl;
  164.  
  165.     {
  166.         LOG_DURATION("set");
  167.         set<VehiclePlate> container;
  168.         for (auto& p : fill_vector) {
  169.             container.insert(p);
  170.         }
  171.         found = count_if(find_vector.begin(), find_vector.end(), [&](const VehiclePlate& plate) {
  172.             return container.count(plate) > 0;
  173.         });
  174.     }
  175.     cout << "Found matches (2): "s << found << endl;
  176. }
  177.  
  178. // log_duration.h
  179.  
  180. #pragma once
  181.  
  182. #include <chrono>
  183. #include <iostream>
  184.  
  185. #define PROFILE_CONCAT_INTERNAL(X, Y) X##Y
  186. #define PROFILE_CONCAT(X, Y) PROFILE_CONCAT_INTERNAL(X, Y)
  187. #define UNIQUE_VAR_NAME_PROFILE PROFILE_CONCAT(profileGuard, __LINE__)
  188. #define LOG_DURATION(x) LogDuration UNIQUE_VAR_NAME_PROFILE(x)
  189.  
  190. class LogDuration {
  191. public:
  192.     // заменим имя типа std::chrono::steady_clock
  193.     // с помощью using для удобства
  194.     using Clock = std::chrono::steady_clock;
  195.  
  196.     LogDuration(const std::string& id) : id_(id) {
  197.     }
  198.  
  199.     ~LogDuration() {
  200.         using namespace std::chrono;
  201.         using namespace std::literals;
  202.  
  203.         const auto end_time = Clock::now();
  204.         const auto dur = end_time - start_time_;
  205.         std::cerr << id_ << ": "s << duration_cast<milliseconds>(dur).count() << " ms"s << std::endl;
  206.     }
  207.  
  208. private:
  209.     const std::string id_;
  210.     const Clock::time_point start_time_ = Clock::now();
  211. };
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement