How to generate 4 different random numbers in C++ - c++

I am making Bulls and Cows assignment from Bjarne Stroustrup's "Programming Principles and Practice Using C++" book (p. 130, exercise 13) and I want program to generate four different integers in the range 0 to 9 (e.g., 1234 but not 1122)
I made a vector to store numbers and a function which generates 4 numbers and adds them to vector, but numbers might be the same and I can't return numbers to main function
#include "../..//..//std_lib_facilities.h"
vector<int> gen4Nums(vector<int> secNum)
{
random_device rd; // obtain a random number from hardware
mt19937 eng(rd()); // seed the generator
uniform_int_distribution<> distr(0, 9); // define the range
secNum.clear();
for (int i = 0; i < 4; i++)
{
secNum.push_back(distr(eng));
cout << secNum[i];
}
return secNum;
}
int main()
{
vector<int> secNum;
gen4Nums(secNum);
}
I expect to return 4 different random numbers to the main function

You can ensure to get different random numbers in the result if you change your code like this:
#include <vector>
#include <random>
#include <algorithm>
using namespace std;
vector<int> gen4Nums()
{
vector<int> result;
random_device rd; // obtain a random number from hardware
mt19937 eng(rd()); // seed the generator
uniform_int_distribution<> distr(0, 9); // define the range
int i = 0;
while(i < 4) { // loop until you have collected the sufficient number of results
int randVal = distr(eng);
if(std::find(std::begin(result),std::end(result),randVal) == std::end(result)) {
// ^^^^^^^^^^^^ The above part is essential, only add random numbers to the result
// which aren't yet contained.
result.push_back(randVal);
cout << result[i];
++i;
}
}
return result;
}
int main() {
vector<int> secNum = gen4Nums();
}

Seems like you're trying to generate 4 unique random integers in the range 0...9.
You can do this by generating a vector of integers containing the values 0...9. Then shuffle the vector, as you want it to be a random selection of the integers. Lastly trimming the vector to the desired size, as you only want 4 unique random integers:
#include <vector>
#include <random>
#include <algorithm>
#include <numeric>
void gen4Nums(std::vector<int>& v) {
//Generate initial vector with values 0...9:
v.resize(10, 0);
std::iota(v.begin(), v.end(), 0);
//Shuffle the vector:
std::random_device rd;
std::mt19937 g(rd());
std::shuffle(v.begin(), v.end(), g);
//Trim the vector to contain only 4 integers:
v.resize(4);
}

Related

All objects made through constructor have the same vectors

I'm new to C++ and I am trying to create a basic genetic algorithm. I created a Chromosome class and want to create a Society class that generates a vector of these Chromosomes with randomly generated "genes". Genes being the vector in the Chromosome that holds values of 0 or 1. I was testing out the Chromosome constructor, and all of the objects have the same gene vectors. How can I make the constructor generate random values? I have included code below. Any other coding practice or optimization tips would also be extremely appreciated.
Source.cpp
#include "Chromosome.h"
#include "Society.h"
using namespace std;
int main()
{
Chromosome demo = Chromosome::Chromosome();
Chromosome demo2 = Chromosome::Chromosome();
return 1;
}
Chromosome.h
#pragma once
#include <vector>
using namespace std;
class Chromosome
{
private:
int fitness;
vector<int> genes;
public:
Chromosome();
void generateGenes();
int calculateFitness(),
getFitness();
vector<int> getGenes();
void setGenes(vector<int> child);
};
Chromosome.cpp
#include "Chromosome.h"
#include <cstdlib>
#include <ctime>
#include <numeric>
using namespace std;
Chromosome::Chromosome()
{
generateGenes();
Chromosome::fitness = calculateFitness();
}
void Chromosome::generateGenes()
{
srand(time(NULL));
for (unsigned i = 0; i < 10; i++)
{
unsigned chance = rand() % 5;
Chromosome::genes.push_back((!chance)? 1 : 0);
}
}
int Chromosome::calculateFitness()
{
int sum = 0;
for (unsigned i = 0; i < Chromosome::genes.size(); i++)
{
sum += Chromosome::genes[i];
}
return sum;
}
int Chromosome::getFitness()
{
return Chromosome::fitness;
}
vector<int> Chromosome::getGenes()
{
return Chromosome::genes;
}
void Chromosome::setGenes(vector<int> child)
{
Chromosome::genes = child;
}
You seed the random number generator with the same value time(NULL).
Two calls after eachother will return the same time_t. You'll generate one set of random numbers first, then reset the random number generator and generate them again.
Only call srand() once during the whole program run.
Also, use <random> instead to get better/faster random number generators.
Instead of rand() % 5; using <random>:
#include <random>
// A function to return a random number generator.
inline std::mt19937& generator() {
// the generator will only be seeded once since it's static
static std::mt19937 gen(std::random_device{}());
return gen;
}
// A function to generate unsigned int:s in the range [min, max]
int my_rand(unsigned min, unsigned max) {
std::uniform_int_distribution<unsigned > dist(min, max);
return dist(generator());
}
Then call it:
unsigned chance = my_rand(0, 4);
Your problem is the use of rand & srand in a C++ program.
srand(time(NULL));
unsigned chance = rand() % 5;
in this implementation, rand might return multiple numbers that will give you the same final result. for example:
19, 24, 190214, 49789, 1645879, 15623454, 4, 156489719, 1645234, 152349, ...
There are different ways of generate random numbers in C++, this one isn't recommended due to bad results.
One (of many) good ways to generate random, using "pseudo-random" in C++:
void Chromosome::generateGenes()
{
// Initialize random
std::random_device rd; // Will be used to obtain a seed for the random number engine
std::mt19937 gen(rd()); // Standard mersenne_twister_engine seeded with rd()
std::uniform_int_distribution<> dis(0, 5);
for (unsigned i = 0; i < 10; i++)
{
// Use random: dis(gen);
unsigned chance = dis(gen);
Chromosome::genes.push_back((!chance)? 1 : 0);
}
}
Include:
#include <random>
Right note by #TedLyngmo: Every time that function will be called (in your case, in every object creation in the constructor call), this code will make you generate a new random seed (In 'Initialize random' section). In more progress cases, or as the program grows, it is highly recommended to extract this initialize to another function (and maybe to a new class object for modular programming reason). In this response I demonstrated the general syntax of using this type of random in your case.
Read about:
Pseudo-random number generation
Uniform Distribution
Thanks to #M.M: How to succinctly, portably, and thoroughly seed the mt19937 PRNG?

Is it possible to select random numbers from a defined set of numbers

Random function usually generates random numbers within a given range. But is it possible to randomly select from a pre-defined list? For example i have [1,4,5,6] and i want to randomly select from this list only. If so, how?
Thanks :)
P.s:: C++ code would help me a big deal ^^
The following code would help, instead of choose a random integer, we can choose a random index in the set;
int numbers[4] = {1,4,5,6};
srand (time(NULL));
int index = rand() % 4;
int number = numbers[index];
Here is a C++11 version utilizing <random> instead:
#include <random>
int numbers[4] = {1,4,5,6};
std::default_random_engine generator;
std::uniform_int_distribution<int> distribution(0,3);
int index = distribution(generator); // generates number in the range 0..3
int number = numbers[index];
Good way to do that might be using shuffle. Basically, you shuffle array and then start to pick numbers one by one
#include <iostream> // std::cout
#include <algorithm> // std::shuffle
#include <array> // std::array
#include <random> // std::default_random_engine
int main () {
std::array<int, 4> foo {1,4,5,6};
std::shuffle(foo.begin(), foo.end(), std::default_random_engine(12345));
std::cout << "shuffled elements:";
for (int x: foo)
std::cout << ' ' << x;
std::cout << '\n';
return 0;
}

Generate random number in range without repetition

I am using C++ to generate n uniform numbers in a given range without repeatition. I want to save it in array(not vector). I found a code but it does not allow to generate number without repetition.
std::random_device rd; // only used once to initialise (seed) engine
std::mt19937 rng(rd()); // random-number engine used (Mersenne-Twister in this case)
std::uniform_int_distribution<int> uni(0,10-1); // guaranteed unbiased
auto random_integer = uni(rng);
For example, I will generate 5 random numbers in range 0-9 such as
1 0 3 8 6
This is my code
typedef unsigned int U32, *PU32;
U32 total_num = 5;
U32 *rndArray = new U32[total_num];
for (U32 i = 0; i < total_num; i++)
{
std::random_device rd // only used once to initialise (seed) engine
std::mt19937 rng(rd());
std::uniform_int_distribution<int> uni(0,10-1);
auto random_integer = uni(rng);
rndArray[i] = random_integer ;
}
Second way, I used the code bellow which allows without repetition. But it is not support in g++ (I am using g++ in ubuntu)
#include <random>
#include <algorithm>
#include <iterator>
#include <iostream>
typedef unsigned int U32;
int main()
{
U32 total_num = 5;
U32 *rndArray = new U32[total_num];
std::random_device rd;
std::mt19937 g(rd());
std::vector<int> v = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
std::shuffle(v.begin(), v.end(), g);
for (int i=0;i<5;i++)
{
rndArray[i]=v[i];
std::cout<< rndArray[i] << " ";
}
std::cout << "\n";
}
There's a couple ways you can do this.
If the random number is already in the array, then generate another one until you find a number that has not been seen before. This is quick to implement but has the disadvantage of very high running time theoretically.
Create the entire range to begin with in an array and then scramble it. To get k numbers, obtain the first k elements of the scrambled array.
Use the Fisher-Yates shuffle algorithm to shuffle a vector/array filled with all the numbers in the desired range: https://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle
The easiest way to achieve what you want is to do what user Untitled123 suggested (see below). To compile: g++ -std=c++11 file.cpp
#include <vector>
#include <algorithm>
using namespace std;
int randomize(const int &i) return rand() % i;
int main() {
srand(unsigned(time(0)));
int n = 10;
vector<int> sample(n);
// generate numbers 0 .. n-1
iota(sample.begin(), sample.end(), 0);
// shuffle elements
random_shuffle(sample.begin(), sample.end(), randomize);
// grab the first five elements after shuffling
vector<int> chosen(sample.begin(), sample.begin() + 5);
// do stuff
return 0;
}

Elegant way to draw n random values in C++11?

For my program, I needed so far to draw one random value in [0..k[ from time to time, and using C++11 <random> features works really well. My current code is something like
class Random
{
public:
Random() : rng( rd() ) { }
inline int getRandNum( int limit ) { return ( numbers(rng) % limit ); }
private:
std::random_device rd;
std::mt19937 rng;
std::uniform_int_distribution<int> numbers;
};
Now, I need to draw in a row n different values in [0..k[. I was looking for something in <random> allowing that, but either I am not able to find it, or such a thing does not exist yet. Is there a clever, more elegant way to proceed than calling my getRandNum function and repeat until I get n different values?
EDIT: to give an idea, in my program k is some thousands and n some tens.
This solution is not C++ specific but can be easily implemented in any language.
What you want is essentially shuffle numbers 0 to k and pick the first n numbers, where n <= k.
This can be done using a reservoir sampling algorithm. See this wikipedia link for the pseudocode.
Note that it is possible to get the n numbers without storing all k numbers and shuffling them. That is, it is possible to just use O(n) space, where n is the number of random numbers you wish to obtain, instead of O(k). The time complexity for this algorithm is O(k), if we assume generating the random number takes O(1) time.
If k is several thousands and n is tens, then a permutation generation is really not the best choise. But calling getRandNum is not what you want too, because it can return the same value several times.
One option is to generate random sequence all at once, checking that the numbers don't repeat. The easiest (and may be even the most efficient) way to achieve this is to use a set.
Like so:
#include <vector>
#include <set>
#include <iostream>
#include <random>
class Random
{
public:
Random() : rng( rd() ) { }
inline int getRandNum( int limit ) { return ( numbers(rng) % limit ); }
std::set<int> getRandSequence(int limit, int n);
private:
std::random_device rd;
std::mt19937 rng;
std::uniform_int_distribution<int> numbers;
};
std::set<int> Random::getRandSequence(int limit, int n)
{
std::set<int> generatedSequence;
while (generatedSequence.size() < n) //size() for set is O(1) if I'm not mistaken
generatedSequence.insert(getRandNum(limit));
return generatedSequence;
}
int main()
{
Random r;
auto sequence = r.getRandSequence(1000, 10);
std::cout << "Seq;uence: " << std::endl;
for (int number : sequence)
std::cout << number << std::endl;
std::cout << "End" << std::endl;
return 0;
}
Ideone demo.
By the way, random_device creation is expensive, but uniform_int_distribution creation, as far as I remember, is not. So this might be even more efficient:
std::set<int> Random::getRandSequence(int limit, int n)
{
std::uniform_int_distribution<int> uiniformDistribution(0, limit);
std::set<int> generatedSequence;
while (generatedSequence.size() < n)
generatedSequence.insert(uiniformDistribution(rng));
return generatedSequence;
}
Besides, when you get a uniform distribution and then apply % limit to it, you don't get a uniform distribution anymore.
std::random_device rd; // obtain a random number from hardware
std::mt19937 eng(rd()); // seed the generator
std::uniform_int_distribution<> distr(0, 1500); // define the range
for(int a=0; a<limit; a++){
cout << distr(eng); //draw random nubmer

random function in C++

Is there a function that generates k random numbers within a specified range.
For example I want 5 random numbers between 0 to 100, with or without replacement.
You could use std::generate_n with either rand() or a generator from the new C++11 random number generators.
There is the Boost library, which you can use to generate random numbers, for example.
The following code generates 5 random numbers from [0, 100] with replacement:
#include <vector>
#include <boost/random/mersenne_twister.hpp>
#include <boost/random/uniform_int_distribution.hpp>
const int numWantedNumbers = 5;
int main()
{
boost::random::mt19937 generator;
boost::random::uniform_int_distribution<> distribution(0, 100);
std::vector<int> result;
for (int i = 0; i < numWantedNumbers; ++i)
result.push_back(distribution(generator));
}
If you want to generate the numbers without replacement, simply check if they are
still available:
#include <algorithm>
#include <vector>
#include <boost/random/mersenne_twister.hpp>
#include <boost/random/uniform_int_distribution.hpp>
const int numWantedNumbers = 5;
int main()
{
boost::random::mt19937 generator;
boost::random::uniform_int_distribution<> distribution(0, 100);
std::vector<int> result;
while (result.size() < numWantedNumbers)
{
int number = distribution(generator);
if (std::find(result.begin(), result.end(), number) == result.end())
result.push_back(number);
}
}
Note: The rejection sampling in the example without replacement has the obvious drawback that longer vectors are quite difficult to create. Just try to draw 99 out
of 100 numbers, to see what I mean (or even better draw 9999 out of 10000). If this
is a problem, I would suggest to create a random permutation of all possible numbers
and then cut the vector at the requested size:
#include <algorithm>
#include <vector>
#include <boost/random/mersenne_twister.hpp>
#include <boost/random/uniform_int_distribution.hpp>
const int numWantedNumbers = 5;
int main()
{
boost::random::mt19937 generator;
boost::random::uniform_int_distribution<> distribution(0, 100);
// Generate a vector with all possible numbers and shuffle it.
std::vector<int> result;
for (int i = 0; i <= 100; ++i)
result.push_back(i);
for (int i = 0; i <= 100; ++i)
{
int x = distribution(generator);
std::swap(result[i], result[x]);
}
// Truncate to the requested size.
result.resize(numWantedNumbers);
}
Edit based on suggestion by juanchopanza:
In C++11 manner, the last variant would look like this
#include <algorithm>
#include <random>
#include <vector>
const int numWantedNumbers = 5;
int main()
{
std::random_device device;
std::mt19937 generator(device());
std::uniform_int_distribution<> distribution(0, 100);
// Generate a vector with all possible numbers and shuffle it.
std::vector<int> result;
for (int i = 0; i <= 100; ++i)
result.push_back(i);
std::random_shuffle(result.begin(), result.end());
// Truncate to the requested size.
result.resize(numWantedNumbers);
}
g++-4.6 compiles it happily, if you add the -std=c++0x switch.
Edit: Make use of std::random_shuffle() (tanks to James Kanze).
Yes there is a rand() function in C++ which can be used including cstdlib header file in your program.
You can implement your program using the following code.
#include <iostream>
#include <cstdlib>
#include <ctime>
using namespace std;
int main()
{
int max {100};
int min {0};
int number;
int count = 5; //assuming that only 10 numbers we need to print
srand(time(0));
for(int i=1;i<=count;i++)
{
number = rand() % (max - min +1) + min;``
cout<<number<<endl;
}
}