fork download
  1. #include <iostream>
  2. #include <string>
  3. #include <array>
  4. #include <random>
  5.  
  6. #define onlyAtEnd(a) typename std::enable_if<sizeof...(a) == 0 > ::type
  7.  
  8. template<int a, int b>
  9. class Entry
  10. {
  11. public:
  12. static constexpr int VAL = a;
  13. static constexpr int PROB = b;
  14. };
  15.  
  16. template<typename... EntryTypes>
  17. class NumChooser
  18. {
  19. private:
  20. const int SUM;
  21. static constexpr int NUM_VALS = sizeof...(EntryTypes);
  22. std::mt19937 gen;
  23. std::uniform_int_distribution<> dist;
  24.  
  25. public:
  26.  
  27. static constexpr int size()
  28. {
  29. return NUM_VALS;
  30. }
  31.  
  32. template<typename T, typename... args>
  33. constexpr int calcSum()
  34. {
  35. return T::PROB + calcSum < args...>();
  36. }
  37.  
  38. template <typename... Ts, typename = onlyAtEnd(Ts) >
  39. constexpr int calcSum()
  40. {
  41. return 0;
  42. }
  43.  
  44. NumChooser() : SUM(calcSum < EntryTypes... >()), gen(std::random_device{}()), dist(1, SUM) { }
  45.  
  46. template<typename T, typename... args>
  47. constexpr int find(int left, int previous = 0)
  48. {
  49. return left < 0 ? previous : find < args... >(left - T::PROB, T::VAL);
  50. }
  51.  
  52. template <typename... Ts, typename = onlyAtEnd(Ts) >
  53. constexpr int find(int left, int previous)
  54. {
  55. return previous;
  56. }
  57.  
  58. int choose()
  59. {
  60. return find < EntryTypes... >(dist(gen));
  61. }
  62. };
  63.  
  64. NumChooser <
  65. Entry<0, 10>,
  66. Entry<1, 50>,
  67. Entry<2, 80>,
  68. Entry<3, 01>
  69. > chooser;
  70.  
  71. int main()
  72. {
  73. std::array<int, chooser.size() > frequency{};
  74. const int NUM_TRIALS = 10000;
  75. for (int i = 0; i < NUM_TRIALS; ++i)
  76. {
  77. int val = chooser.choose();
  78. frequency[val]++;
  79. }
  80. std::cout << "Frequency:" << std::endl;
  81. for (int i : frequency)
  82. std::cout << (float) i / NUM_TRIALS << " ";
  83. }
Success #stdin #stdout 0s 3464KB
stdin
Standard input is empty
stdout
Frequency:
0.0656 0.3522 0.5659 0.0163