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