HELP

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
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
  #include <iostream>
#include <ctime>
#include <vector>
#include <iomanip>
#include<algorithm>

const int SIZE =10;
unsigned int seed = (unsigned)time(0);
using namespace std;

double random (unsigned int &seed);
void print_vector (vector<int> :: iterator b,
                   vector<int> :: iterator e );
void initialize_vector(vector<int> &v);
vector<int>v;

int main()
{
    cout << endl;
    initialize_vector(v);
    cout << "Vector : " << endl;
    print_vector(v.begin(), v.end());
    return 0;
}

double random(unsigned int &seed)
{
    const int MODULUS = 15749;
    const int MULTIPLIER = 69069;
    const int INCREMENT = 1;
    seed = ((MULTIPLIER*seed)+INCREMENT)%MODULUS;
    return double (seed)/MODULUS;
}

void initialize_vector(vector<int> &v)
{
    for (int i=0; i<SIZE; i++)
        v.push_back(random(seed)*(2*SIZE+1));
}

void print_vector (vector<int> :: iterator b,
                   vector<int> :: iterator e )
{
    vector<int> :: iterator p =b;
    while(p<e)
        cout << setw(3) << (*p++);
    cout << endl;
}
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.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
#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/random
    static 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#auto
    for( const auto& v : seq ) std::cout << v << ' ' ;

    std::cout << "]\n" ;
}

int main()
{
    const std::size_t SIZE = 25 ;

    const auto vec = make_vector(SIZE) ;
    print(vec) ;
}

http://coliru.stacked-crooked.com/a/f33f4d0734b88712
Last edited on
1
2
3
4
5
std::vector<int> set( SIZE*2 + 1 );
std::iota( set.begin(), set.end(), 0 ); // fill with [0..2*SIZE]
unsigned seed = std::chrono::system_clock::now().time_since_epoch().count();
std::shuffle( set.begin(), set.end(), std::mt19937(seed) );
set.resize( SIZE ); // keep SIZE unique random values 
can you edit my initialize vector so it has only unique numbers?
yes.
can you? We gave you the tools to do it. If you don't understand it, ask something.
give it a try.
Last edited on
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).
Topic archived. No new replies allowed.