#include <iostream>
#include <string>
#include <array>
#define onlyAtEnd(a) typename std::enable_if<sizeof...(a) == 0 > ::type
template<int a, int b>
class Entry
{
public:
static constexpr int VAL = a;
static constexpr int PROB = b;
};
template<typename... EntryTypes>
class NumChooser
{
private:
const int SUM;
static constexpr int NUM_VALS = sizeof...(EntryTypes);
public:
static constexpr int size()
{
return NUM_VALS;
}
template<typename T, typename... args>
constexpr int calcSum()
{
return T::PROB + calcSum < args...>();
}
template <typename... Ts, typename = onlyAtEnd(Ts) >
constexpr int calcSum()
{
return 0;
}
NumChooser() : SUM(calcSum < EntryTypes... >()) { }
template<typename T, typename... args>
constexpr int find(int left, int previous = 0)
{
return left < 0 ? previous : find < args... >(left - T::PROB, T::VAL);
}
template <typename... Ts, typename = onlyAtEnd(Ts) >
constexpr int find(int left, int previous)
{
return previous;
}
constexpr int choose()
{
return find < EntryTypes... >(rand() % SUM);
}
};
NumChooser <
Entry<0, 10>,
Entry<1, 50>,
Entry<2, 80>,
Entry<3, 01>
> chooser;
int main()
{
srand(time(nullptr));
std::array<int, chooser.size() > frequency{};
const int NUM_TRIALS = 10000;
for (int i = 0; i < NUM_TRIALS; ++i)
{
int val = chooser.choose();
frequency[val]++;
}
std::cout << "Frequency:" << std::endl;
for (int i : frequency)
std::cout << (float) i / NUM_TRIALS << " ";
}
I2luY2x1ZGUgPGlvc3RyZWFtPgojaW5jbHVkZSA8c3RyaW5nPgojaW5jbHVkZSA8YXJyYXk+CgojZGVmaW5lIG9ubHlBdEVuZChhKSB0eXBlbmFtZSBzdGQ6OmVuYWJsZV9pZjxzaXplb2YuLi4oYSkgPT0gMCA+IDo6dHlwZQoKdGVtcGxhdGU8aW50IGEsIGludCBiPgpjbGFzcyBFbnRyeQp7CnB1YmxpYzoKCXN0YXRpYyBjb25zdGV4cHIgaW50IFZBTCA9IGE7CglzdGF0aWMgY29uc3RleHByIGludCBQUk9CID0gYjsKfTsKCnRlbXBsYXRlPHR5cGVuYW1lLi4uIEVudHJ5VHlwZXM+CmNsYXNzIE51bUNob29zZXIKewpwcml2YXRlOgoJY29uc3QgaW50IFNVTTsKCXN0YXRpYyBjb25zdGV4cHIgaW50IE5VTV9WQUxTID0gc2l6ZW9mLi4uKEVudHJ5VHlwZXMpOwoKcHVibGljOgoKCXN0YXRpYyBjb25zdGV4cHIgaW50IHNpemUoKQoJewoJCXJldHVybiBOVU1fVkFMUzsKCX0KCgl0ZW1wbGF0ZTx0eXBlbmFtZSBULCB0eXBlbmFtZS4uLiBhcmdzPgoJY29uc3RleHByIGludCBjYWxjU3VtKCkKCXsKCQlyZXR1cm4gVDo6UFJPQiArIGNhbGNTdW0gPCBhcmdzLi4uPigpOwoJfQoKCXRlbXBsYXRlIDx0eXBlbmFtZS4uLiBUcywgdHlwZW5hbWUgPSBvbmx5QXRFbmQoVHMpID4KCWNvbnN0ZXhwciBpbnQgY2FsY1N1bSgpCgl7CgkJcmV0dXJuIDA7Cgl9CgoJTnVtQ2hvb3NlcigpIDogU1VNKGNhbGNTdW0gPCBFbnRyeVR5cGVzLi4uID4oKSkgeyB9CgoJdGVtcGxhdGU8dHlwZW5hbWUgVCwgdHlwZW5hbWUuLi4gYXJncz4KCWNvbnN0ZXhwciBpbnQgZmluZChpbnQgbGVmdCwgaW50IHByZXZpb3VzID0gMCkKCXsKCQlyZXR1cm4gbGVmdCA8IDAgPyBwcmV2aW91cyA6IGZpbmQgPCBhcmdzLi4uID4obGVmdCAtIFQ6OlBST0IsIFQ6OlZBTCk7Cgl9CgoJdGVtcGxhdGUgPHR5cGVuYW1lLi4uIFRzLCB0eXBlbmFtZSA9IG9ubHlBdEVuZChUcykgPgoJY29uc3RleHByIGludCBmaW5kKGludCBsZWZ0LCBpbnQgcHJldmlvdXMpCgl7CgkJcmV0dXJuIHByZXZpb3VzOwoJfQoKCWNvbnN0ZXhwciBpbnQgY2hvb3NlKCkKCXsKCQlyZXR1cm4gZmluZCA8IEVudHJ5VHlwZXMuLi4gPihyYW5kKCkgJSBTVU0pOwoJfQp9OwoKTnVtQ2hvb3NlciA8CkVudHJ5PDAsIDEwPiwKRW50cnk8MSwgNTA+LApFbnRyeTwyLCA4MD4sCkVudHJ5PDMsIDAxPgo+IGNob29zZXI7CgppbnQgbWFpbigpCnsKCXNyYW5kKHRpbWUobnVsbHB0cikpOwoJc3RkOjphcnJheTxpbnQsIGNob29zZXIuc2l6ZSgpID4gZnJlcXVlbmN5e307Cgljb25zdCBpbnQgTlVNX1RSSUFMUyA9IDEwMDAwOwoJZm9yIChpbnQgaSA9IDA7IGkgPCBOVU1fVFJJQUxTOyArK2kpCgl7CgkJaW50IHZhbCA9IGNob29zZXIuY2hvb3NlKCk7CgkJZnJlcXVlbmN5W3ZhbF0rKzsKCX0KCXN0ZDo6Y291dCA8PCAiRnJlcXVlbmN5OiIgPDwgc3RkOjplbmRsOwoJZm9yIChpbnQgaSA6IGZyZXF1ZW5jeSkKCQlzdGQ6OmNvdXQgPDwgKGZsb2F0KSBpIC8gTlVNX1RSSUFMUyA8PCAiICI7Cn0=