Suppose that you want to generate N random numbers but that you
want a determined number of replications for each of them: for example
you want 10 times the number 1, 25 times the number 2 and 15 times
the number 3. Using the std::random() function does not guarantee
you that after 50 extractions you have the desired number of replications
for each number. My solution is to provide a class, which does that:
class RandomListInt
{
public:
RandomListInt();
Init(const std::vector<unsigned
int>& items_);
int GetNext();
unsigned int Size() const;
private:
std::list<std::pair<int,
unsigned int> > RndList;
... // some more stuff
};
The Init member function receives a std::vector<unsigned
int> which represents the number of replications that one
wants to generate for each element of the vector. In our case 10,
25 and 15.
Its body is:
RandomListInt::Init(const std::vector<unsigned int>&
items)
{
RndList.clear();
for (int i = 0; i < items.size(); i++)
for (int c = 0; c < items[i];
c++)
RndList.push_back(std::make_pair(i,
random(std::numeric_limits<int>::max())));
RndList.sort(lower_rnd);
}
For each of the 3 elements a number of items equal to the number
that they represents are stored in a std::list with associated
a randomly generated number through a std::pair. Then, the
list is sorted depending on the associated random number.
Calls to the GetNext() member will return the index of the
vector passed to the Init(...) function and remove the pair
from the list.
int RandomListInt::GetNext()
{
int val = RndList.front().first;
RndList.pop_front();
return val;
}
When the RndList is empty (that is when Size() returns 0),
the randomization is completed.
An example of its use is the following one, where GetEventsCount()
and events are members of a SimpleProtocol class of mine, and rnd_list
is an instance of RandomListInt:
if (!bInitialized)
{
std::vector<unsigned int>vv_;
vv_.reserve(GetEventsCount());
for (unsigned int i = 0; i < GetEventsCount();
i++)
vv_.push_back(events[i]->GetTrialsCount());
rnd_list.Init(vv_);
}
if (rnd_list.Size())
return rnd_list.GetNext();
else
..// randomization completed!
|