shushus

Спринт 10. Хорошие и плохие хеш-функции.

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