Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Random choices of two values

In my algorithm I have two values that I need to choose at random but each one has to be chosen a predetermined number of times.

So far my solution is to put the choices into a vector the correct number of times and then shuffle it. In C++:

// Example choices (can be any positive int)
int choice1 = 3; 
int choice2 = 4;

int number_of_choice1s = 5;
int number_of_choice2s = 1;

std::vector<int> choices;
for(int i = 0; i < number_of_choice1s; ++i) choices.push_back(choice1);
for(int i = 0; i < number_of_choice2s; ++i) choices.push_back(choice2);
std::random_shuffle(choices.begin(), choices.end());

Then I keep an iterator to choices and whenever I need a new one I increase the iterator and grab that value.

This works but it seems like there might be a more efficient way. Since I always know how many of each value I'll use I'm wondering if there is a more algorithmic way to go about doing this, rather than just storing the values.

like image 936
Sean Lynch Avatar asked May 10 '12 19:05

Sean Lynch


2 Answers

You are unnecessarily using so much memory. You have two variables:

int number_of_choice1s = 5;
int number_of_choice2s = 1;

Now simply randomize:

int result = rand() % (number_of_choice1s + number_of_choice2s);
if(result < number_of_choice1s) {
  --number_of_choice1s;
  return choice1;
} else {
  --number_of_choice2s;
  return choice2;
}

This scales very well two millions of random invocations.

like image 116
Tomasz Nurkiewicz Avatar answered Oct 19 '22 09:10

Tomasz Nurkiewicz


You could write this a bit more simply:

std::vector<int> choices(number_of_choice1s, choice1);
choices.resize(number_of_choice1s + number_of_choice2s, choice2);
std::random_shuffle(choices.begin(), choices.end());
like image 1
Kerrek SB Avatar answered Oct 19 '22 11:10

Kerrek SB