Random number generation - repetition problems

Hi there everyone!

I am a beginning C++ programmer and I am trying to create a program which is similar to a 6-number lottery. Basically, it will generate 6 random numbers from 1-50 with no repetition and then display them. However, despite my best efforts I have not been able to prevent the program from repeating numbers. In my code below, my idea was basically to "null out" the numbers I have already used, and for the code to skip over those numbers, but it doesn't work properly. I still get repeated numbers, so the program isn't "skipping over" the nulled out values. Of note is that I have never gotten 0 when I run the program, so it isn't selecting those either. Can anyone offer me some guidance as to how to prevent the repeated selection of numbers?

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
#include <iostream>
#include <cstdio>
#include <cstdlib>  // for rand functions
#include <ctime>    // for time functions

using namespace std;
int main()
{

    int lotteryPool[50];
    for (int x=0; x<50;x=x+1) // generates an array of all 50 possible numbers
    {
    lotteryPool[x] = x+1;
    }                         

    srand( time(NULL));        // using time as a random seed.
    int randomIndex;
    int x;
    for (x = 0; x<6; x++)      // iterating through six numbers
    {
        randomIndex = rand() % 50; // generating a random index to pick
        if (lotteryPool[randomIndex] != 0)  // if the value is nulled, we skip it.
        {
            cout << lotteryPool[randomIndex] << " "; // if it is not null, we print it...
            lotteryPool[randomIndex] == 0;           // then null it to make sure it isn't used again.
        }
    }
return 0;
}


In my experience the rand() function isn't really random. If you keep repeating the program you will most likely see the same numbers. If you are saying that when iterating through six numbers the the random numbers are repeating then just call an if statement that gets a new random number if it is repeated.
Hi Gawaine,

So for instance one of my test runs was:

3 39 50 33 22 33

I was trying to use the if statement in my code (line 22) as a way of doing what you said, and getting a new random number if it is repeated. I planned on doing that by "nulling" the value of an index that has already been used, and then getting a new number. But that isn't working. Is there a better way to do this?
Last edited on
Line 25: You're not nulling out the entry. You're using the equality operator (==), not the assignment operator (=).

Note: Your for loop at line 19 doesn't guarantee you that you will find 6 non-duplicates. Lets say you find one duplicate. You suppress that, displaying only 5 numbers.
what you could do is search the array or the six specific numbers to see if a number repeats and then call the rand() function again. I'm pretty sure your if statement won't do anything but print out the numbers in the array.

Also in your for loop for (int x=0; x<50;x=x+1), change the x=x+1 tox++.
x++; or for example x-- means x=x+1 or x=x-1 respectively.
Ah, okay. So, if I hit a duplicate, nothing will happen. I've just run this code again and seen the problem. Is there a way that I could just restart that iteration, instead of skipping it entirely and moving on to the next one in the for loop? (I come from a python background so I am fairly incompetent at this sort of manipulation).

Thanks for your responses everyone!
Hi zeberwood,

you should really take into account what Gawaine said.

Here's something better http://www.cplusplus.com/reference/random/

Using #include <random> and using any of the pseudo-random number generators might help to output a more random number.

I'm in the same position you are in and this seems to be the way to go for a random number.

I'll definitely look into it Stoneynine. And I'm going to replace rand() wherever possible from now on. For this program in particular though, I need a way to guarantee that there is no repetition. That's where I am falling down. It's just like a long string of problems that pop up whenever I change anything.
@zeberwood

I was helping someone write a BINGO filling card program, and used this, to be sure each number was different in each column. Maybe you can use part of it for your solution.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
do{

		//cout<<"\n\n\t\t\t\t    BINGO GAME"<<endl;
		//cout<<"\n\n\tB\t\tI\t\tN\t\tG\t\tO"<<endl;
		cout<<"\n\n";
		for(col = 0;col < 5; col++)
		{
			for (row=0;row < 5; row++)
			{
				do
				{
					ok = true;
					number = 1+(col*15) + rand()%15;
					for (int ck=0;ck<5;ck++)
					{
						if (number == num[ck][col])
								ok = false;
					}
				}while (!ok);
			num[row][col] = number;
			}
		}


This, of course, is for 5 columns, but the principle is the same . Hope it helps. Let me know if you need assistance using it in your program.
I think it would be better to use a while loop and a counter that counts to six. Therefore you can keep running the loop till you get a number that wasn't repeated and if the number isn't repeated count++ until count is 6.

Good luck
Can you elaborate on how that might be done? It seems like that would just return the same thing, if it is still counting to 6.
Hi, maybe it will help to see what I am trying to do. I tried to use a while loop for the same thing, but now it is not returning anything. I really don't know what to do. I'm totally lost.

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
#include <iostream>
#include <cstdio>
#include <cstdlib>  // for rand functions
#include <ctime>    // for time functions

using namespace std;
int main()
{
    int x;
    int lotteryPool[50];
    for (x=0; x<50; x++) // generates an array of all 50 possible numbers
    {
    lotteryPool[x] = x+1;
    }                         // indexes range from [0] to [49]

    srand( time(NULL));        // using time as a random seed.
    int randomIndex;
    int y=0;
    while (y <= 6);
    {
        randomIndex = rand() % 50; // generating a random index to pick
        if (lotteryPool[randomIndex] != 0)  // if the value is nulled, we skip it.
        {
            cout << lotteryPool[randomIndex] << " "; // if it is not null, we print it...
            lotteryPool[randomIndex] = 0;   // then null it to make sure it isn't used again.
            y++;
        }

    }
return 0;
}
I am a beginning C++ programmer and I am trying to create a program which is similar to a 6-number lottery.


1
2
3
4
5
    int lotteryPool[50];
    for (int x=0; x<50;x=x+1) // generates an array of all 50 possible numbers
    {
    lotteryPool[x] = x+1;
    }                         


That's good. Each lotteryPool element has a unique id. How does it work when the lottery numbers are picked? One is picked at random and... what keeps that number from being picked again? It is removed from the pool. It can't be picked again.

How do we accomplish this in code? Pick a ball at random. Record it. Swap that element with the last element of your pool and reduce the size of the pool by one. Repeat until finished.
It seems like that would just return the same thing

No. As I pointed out before, the for loop as you have written it will output only 6-n values, where n is the number of duplicates. You probably want to use a do/while loop.

1
2
3
4
5
6
7
8
9
10
int number_found = 0;
int i = 0;
do 
{  if (lotteryPool[i])
    { cout << lotteryPool[i] << endl;
       number_found++;  // Count of uniques
       lotteryPool[i] = 0;  // Mark as used
    }
    i++;
} while (number_found < 6 && i < 50);



You could also just shuffle a container of numbers, and select the first six elements or so. That way you're guaranteed that no two numbers are the same.

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 <algorithm>
#include <iostream>
#include <ctime>

int main(int argc, char* argv[]) {

	std::srand(unsigned (std::time(0)));

	const unsigned short num_numbers = 5;
	unsigned short numbers[num_numbers] = { 1, 2, 3, 4, 5 };

	std::cout << "Before shuffle:\t";
	for (auto it : numbers) {
		std::cout << it << ", ";
	}
	std::cout << std::endl;

	std::random_shuffle(numbers, numbers + num_numbers);

	std::cout << "After shuffle:\t";
	for (auto it : numbers) {
		std::cout << it << ", ";
	}
	std::cout << std::endl;
	std::cin.get();
	return 0;
}
Hi everyone,

I think I have a solution working. I used xismn's idea of creating a random shuffle and then pulling out the first six elements, but I wrote it slightly differently. So far it hasn't yielded any duplicate results, and looking at the code I don't think it should be possible.

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 <iostream>
#include <cstdio>
#include <cstdlib>  // for rand functions
#include <ctime>    // for time functions
#include <algorithm> // for access to random_shuffle

using namespace std;
int main()
{

    int lotteryPool[50];
    for (int x=0; x<50;x=x+1) // generates an array of all 50 possible numbers
    {
    lotteryPool[x] = x+1;
    }                         // indexes range from [0] to [49]

    srand( time(NULL) );      // We use time as a random seed.
    random_shuffle(&lotteryPool[0], &lotteryPool[49]); // shuffling the pool

    int x;
    for (x=0; x<6; x++)
    {
    cout << lotteryPool[x] << " ";  // we pull out the first 6 elements and display them.
    }
    return 0;
}
 


Thanks to everyone for all your help. I am currently investigating a way to solve this problem using the do-while loop with the ultimate goal of demonstrating several possible ways to solve this problem. I really appreciate all of your help.
Topic archived. No new replies allowed.