Random numbers: No repeats

Mar 30, 2012 at 2:23pm
I'm attempting to fill an array of size 200 with random numbers between 1 and 1000 but I can have no repeats, and the way I'm currently doing it gives me an infinite loop, I'm assuming because it detects repeats so much. is there a better way than this, or an algorithm you could recommend, that will accomplish this better?

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
//within main

    srand(time(NULL));

	x=0;
	cout << x;
	

	do
	{
		numbers[x]=rand() % 1000+1;
		cout << numbers[x] << endl; //debug
		y=0;

		do
		{

			if(numbers[x]==numbers[y])
			{x--; break;}

			y++;
			cout << numbers[x] << endl; //debug

		}while(y<(x-1));

		x++;
	}while(x<200);


EDIT: The debug statements were for me to see if any values were being assigned. My breakpoints never did anything for some reason.
Last edited on Mar 30, 2012 at 2:24pm
Mar 30, 2012 at 2:38pm
If you change the inner loop to a while loop it will work better.
Mar 30, 2012 at 2:44pm
Why is that?
Mar 30, 2012 at 2:47pm
Think about what happens on the first iteration.
Last edited on Mar 30, 2012 at 2:47pm
Mar 30, 2012 at 2:57pm
so the first iteration is ALWAYS going to flag the inner loop?
Mar 30, 2012 at 2:59pm
It depends on what you mean by "flag".
Mar 30, 2012 at 2:59pm
Take a look at what value x has. Take a look at what value y has. In the first iteration.

Now look at that if statement.....
Mar 30, 2012 at 3:03pm
The first check will always be numbers[0]==numbers[0] and will always break the loop, returning to the initialization of numbers[0] which will (again) equal numbers[0], and so on. Ahhhhh.

So, why would a while loop correct that?
Edit: Would it be better to compare to y-1?
Last edited on Mar 30, 2012 at 3:04pm
Mar 30, 2012 at 3:07pm
Do you know the difference between a while and do-while loop?

Edit: Would it be better to compare to y-1?

No
Mar 30, 2012 at 3:08pm
While checks the loop condition before executing, and do-while checks the loop condition after executing, correct?
Mar 30, 2012 at 3:08pm
> fill an array of size 200 with random numbers between 1 and 1000 but I can have no repeats

One way to do this in linear time is:
a. create a sequence of 1000 numbers [1,2,3,...,1000].
b. shuffle the sequence randomly.
c. pick up the first 200 numbers.

for example:
1
2
3
4
5
6
7
8
9
10
enum { N = 200, M = 1000 } ;

std::vector<int> seq(M) ;
std::iota( seq.begin(), seq.end(), 1 ) ;

std::random_device rand_dev ;
std::mt19937 twister( rand_dev() ) ;
std::shuffle( seq.begin(), seq.end(), twister ) ;

seq.resize(N) ;


Mar 30, 2012 at 3:10pm
or you could use a set?

1
2
3
4
5
6
7
8
9
10
std::set<int> nums;

while(nums.size() < 200)
{
  nums.insert( rand() % 1000 );
}

int array[200];
std::copy( nums.begin(), nums.end(), array );
std::random_shuffle( array, array + 200 );

Last edited on Mar 30, 2012 at 3:11pm
Mar 30, 2012 at 3:19pm
I see now that the loop condition should actually be y<x.

If you use the while loop it will not enter the inner loop because y<x is false when x and y equals zero.
Last edited on Mar 30, 2012 at 3:20pm
Mar 30, 2012 at 3:44pm
JLBorges,

It took me a while to find std::random_device and std::mt19937, but what is std::shuffle and which header is it in?
Mar 30, 2012 at 3:49pm
Stewbond,
I think JLBorges was referring to random_shuffle, which is in the <algorithm>
header.

http://cplusplus.com/reference/algorithm/random_shuffle/

random_shuffle takes two iterators, one pointing to the beginning of your array and one pointing to the end (pointers to elements of an array count as iterators), and optionally a function that can be used to generate random numbers to determine which elements should be shuffled.

-Albatross
Last edited on Mar 30, 2012 at 3:51pm
Mar 30, 2012 at 5:27pm
std::shuffle was introduced with the latest standard.

http://en.cppreference.com/w/cpp/algorithm/random_shuffle
Mar 30, 2012 at 5:29pm
Oh, okay. I see. Thanks for letting me know!

-Albatross
Apr 2, 2012 at 2:53pm
I tried using JLBorges solution (though mine is somewhat simpler looking, I think) and got an error. Here's the code

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
#include <stdlib.h>
#include <iostream.h>
#include <time.h>
#include <vector>
#include <algorithm>

using std::vector;

std::vector<int> Num_Array;
int x, y, z;


void main()
{
	
srand(unsigned(time(NULL)));
	
	x=0;

	for(x=0; x<1001; x++) Num_Array.push_back(x);

	random_shuffle(Num_Array.begin(), Num_Array.end());

	for(x=0; x<201; x++) cout << Num_Array[x] << '\t';

}


g:\c++\2004_four_two\2004_four_two.cpp(22) : error C2065: 'random_shuffle' : undeclared identifier

I was under the impression that random_shuffle was contained in algorithm.h

I know that my headers have .h, that's because I have to use an ancient compiler, Vc++ 6.0 Enterprise
Apr 2, 2012 at 2:59pm
1
2
//random_shuffle(Num_Array.begin(), Num_Array.end());
std::random_shuffle(Num_Array.begin(), Num_Array.end());
Apr 2, 2012 at 3:03pm
Thank you! Works now:)
Topic archived. No new replies allowed.