My program is to write a c++ prgoram initializes an integer vector v of size SIZE with distinct random integers each in range [0,2*SIZE], how can i ensure all are unique
The c++ tools way:
load up a vector with 0- 2*n just 0,1,2,3,... 2*n as the values.
then shuffle it:
shuffle (foo.begin(), foo.end(), std::default_random_engine(seed));
and then peel off the first 1/2.
the DIY way:
allocate a boolean vector 0-2n and set them all false.
generate randoms and mark true when seen, if seen, re-roll.
#include <iostream>
#include <vector>
#include <numeric>
#include <algorithm>
#include <random>
// return an integer vector of size SIZE initialised with
// istinct random integers each in range [0,2*SIZE]
std::vector<int> make_vector( std::size_t SIZE )
{
// create a vector of size 2*SIZE + 1
std::vector<int> vec( 2*SIZE + 1 ) ;
// fill it with consecutive integers in the range [0,2*SIZE]
// https://en.cppreference.com/w/cpp/algorithm/iota
std::iota( vec.begin(), vec.end(), 0 ) ;
// shuffle it randomly such that each possible permutation of
// numbers in [0,2*SIZE] has equal probability
// https://en.cppreference.com/w/cpp/algorithm/random_shuffle
// https://en.cppreference.com/w/cpp/numeric/randomstatic std::mt19937 rng( std::random_device{}() ) ;
std::shuffle( vec.begin(), vec.end(), rng ) ;
// resize the vector to hold the first SIZE numbers after the random shuffle
vec.resize(SIZE) ;
return vec ;
}template < typename SEQUENCE > void print( const SEQUENCE& seq )
{
std::cout << "[ " ;
// range vased loop: http://www.stroustrup.com/C++11FAQ.html#for
// auto: http://www.stroustrup.com/C++11FAQ.html#autofor( constauto& v : seq ) std::cout << v << ' ' ;
std::cout << "]\n" ;
}
int main()
{
const std::size_t SIZE = 25 ;
constauto vec = make_vector(SIZE) ;
print(vec) ;
}
There's no need to shuffle all 2*SIZE items in the vector. Just pick off SIZE random values from it while ensuring that each one can't be chosen again:
- Create the vector
- Pick a random index: 0 <= index < size
- vec[index] is the first item
- swap vec[0] with vec[index]
- Now pick a random index 1 <= index < size
- vec[index] is the next item
- swap vec[1] with vec[index]
- etc.
good point. I wonder if the optimized built in shuffle is 'more actual work done but faster' or if this is the better way (less work, tailored to the problem).