#ifndef DRAWLIST_H #define DRAWLIST_H #include #include #include /** * add elements of a certain probability * and randomly draw from them */ template class DrawList { /** one entry */ struct Entry { /** the user element */ T element; /** the cumulative probability up to this element */ double cumProbability; /** ctor */ Entry(T element, const double cumProbability) : element(element), cumProbability(cumProbability) {;} /** compare for searches */ bool operator < (const double val) const {return cumProbability < val;} }; private: /** current cumulative probability */ double cumProbability; /** all contained elements */ std::vector elements; /** random number generator */ std::minstd_rand gen; public: /** ctor */ DrawList() : cumProbability(0) { ; } /** reset */ void reset() { cumProbability = 0; elements.clear(); } /** add a new user-element and its probability */ void add(T element, const double probability) { cumProbability += probability; elements.push_back(Entry(element, cumProbability)); } /** get a random element based on its probability */ T get() { // generate random number between [0:cumProbability] std::uniform_real_distribution<> dist(0, cumProbability); // get a random value const double rndVal = dist(gen); // binary search for the matching entry O(log(n)) const auto tmp = std::lower_bound(elements.begin(), elements.end(), rndVal); // sanity check _assertFalse(tmp == elements.end(), "draw() did not find a valid element"); // done return (*tmp).element; } /** get the current, cumulative probability */ double getCumProbability() const { return cumProbability; } }; #endif // DRAWLIST_H