Advertisement
Guest User

Untitled

a guest
May 21st, 2019
79
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 2.54 KB | None | 0 0
  1. #include <set>
  2. #include <random>
  3. #include <cassert>
  4. #include <climits>
  5. #include <cstdlib>
  6. #include <hash_fun.h>
  7. #include <iostream>
  8. #include <cmath>
  9.  
  10.  
  11. class UniqCounter {
  12. public:
  13.     UniqCounter() {
  14.         array.assign(size, 0);
  15.     }
  16.  
  17.     void add(int x) {
  18.         unsigned int hash = my_hash(x);
  19.         unsigned int mask = hash >> (32 - K);
  20.         array[mask] = std::max(array[mask], phi(hash));
  21.     }
  22.  
  23.     int get_uniq_num() const {
  24.         double c = 0;
  25.         double res = alpha * size * size;
  26.         for(size_t i = 0; i < size; i++) {
  27.             c += 1.0 / (1LL << array[i]);
  28.         }
  29.         res = res / c;
  30.         if (res <= 2.5 * size) {
  31.             int delta = 0;
  32.             for (size_t i = 0; i < size; ++i) {
  33.                 delta += array[i] == 0;
  34.             }
  35.             if (delta > 0) {
  36.                 res = size * log((1.0 * size) / delta);
  37.             }
  38.         }
  39.         else if (res > 1.0 / 30 * (1LL << 32)) {
  40.             res = -(1LL << 32) * log(1 - res / (1LL << 32));
  41.         }
  42.  
  43.         return static_cast<int>(res);
  44.     }
  45.  
  46. private:
  47.     const size_t K = 10;
  48.     long long size = (1 << K);
  49.     double alpha = 0.7213 / (1 + 1.079 / size);
  50.     std::vector<long long> array;
  51.  
  52.     unsigned int my_hash(int number) {
  53.         unsigned int key = number;
  54.         key += ~(key << 16);
  55.         key ^=  (key >>  5);
  56.         key +=  (key <<  3);
  57.         key ^=  (key >> 13);
  58.         key += ~(key <<  9);
  59.         key ^=  (key >> 17);
  60.         return key;
  61.     }
  62.  
  63.     long long phi(int x) {
  64.         long long res = 0;
  65.         while(((x >> res) & 1) == 0 && res <= (32 - K)) {
  66.             res++;
  67.         }
  68.         return res + 1;
  69.     }
  70. };
  71.  
  72. double relative_error(int expected, int got) {
  73.     return abs(got - expected) / (double) expected;
  74. }
  75.  
  76. int main() {
  77.     std::random_device rd;
  78.     std::mt19937 gen(rd());
  79.     const int N = (int) 1e6;
  80.     for (int k : {1, 10, 1000, 10000, N / 10, N, N * 10}) {
  81.         std::uniform_int_distribution<> dis(1, k);
  82.         std::set<int> all;
  83.         UniqCounter counter;
  84.         for (int i = 0; i < N; i++) {
  85.             int value = dis(gen);
  86.             all.insert(value);
  87.             counter.add(value);
  88.         }
  89.         int expected = (int) all.size();
  90.         int counter_result = counter.get_uniq_num();
  91.         double error = relative_error(expected, counter_result);
  92.         printf("%d numbers in range [1 .. %d], %d uniq, %d result, %.5f relative error\n", N, k, expected, counter_result, error);
  93.         assert(error <= 0.1);
  94.     }
  95.  
  96.     return 0;
  97. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement