Hello, I'm new here. I am trying to make a program that simulates the game Lotto. I have managed to get it to input numbers, but, I cannot figure out how to stop it from having the same number appear twice on the same line.

Below is what I currently have. 'n' is the amount of tickets the person is buying. I have shown what header files I have so you don't need to worry about putting std in.

#include<iostream>
#include<conio>
#pragma hdrstop
using namespace std;
#include <tchar.h>


int ticketGenerator( int n )
{
	int lines[ 30 ] [ 11 ] [ 6 ];
	int num = 11;

	for ( int i = 0; i < n; i++ )
	{
		for ( int j = 0; j < 11; j++ )
		{
			for ( int k = 0; k < 6; k++ )
			{
				lines [ i ] [ j ] [ k ] = 1 + rand() % 40;

			}
		}
	}




	for ( int i = 0; i < n; i++ )
	{
		for ( int j = 0; j < 11; j++ )
		{
			for ( int k = 0; k < 6; k++ )
			{
				cout << lines [ i ] [ j ] [ k ] << " ";
			}
			cout << endl << endl;
		}
		cout << endl << endl << endl << endl;
	}

}

you will have to implement some means of checking the numbers already assigned to a row. either iterate through the numbers already picked, and if any match the new number, discard it and generate a new one.

Or, a bit quicker, set up an array of size 40 (or 41), set it to all zeroes before generating a row. As you pick a number, check if the value at that index is not zero. If so, store the number to your ticket row and set the check array element to 1, otherwise generate a new number.

Thank you vmanes for your help. I have implemented your second paragraph, but I didn't quite understand it. I've managed to come up with this though

int lines[ 30 ] [ 11 ] [ 6 ];
	int num [ 40 ];
	int holder;


	for ( int a = 0; a < 40; a++ )
	{
		num [ a ] = 0;
	}

	for ( int i = 0; i < n; i++ )
	{
		for ( int j = 0; j < 11; j++ )
		{
			for ( int k = 0; k < 6; k++ )
			{


				holder = 1 + rand() % 40;

				if ( num [ k ] != 0 )
				{
					lines [ i ] [ j ] [ k ] = holder;
					num [ k ] = 1;
				}
				else
					holder = 1 + rand() % 40;

			}
		}
	}

if ( num [ k ] != 0 ) your references to num array should should be using holder-1 as the index, not the position in the lotto line you're filling. The num array is keeping track of what's been used, the values that holder holds.

and, at the beginning of the j loop, you need to loop through num array resetting it to all 0s.

think about the typical Lotto game, and how the numbers are selected: you have 40 balls rolling around in a container from which 6 are picked, one at a time, at random.

after each successive pick, the pool of available numbers able to be selected is reduced in size by one element.

first pick:  select 1 of 40 total
second pick:  select 1 of 39 total
third pick:  select 1 of 38 total
fourth pick:  select 1 of 37 total
fifth pick:  select 1 of 36 total
sixth pick:  select 1 of 35 total

therefore, it is not an accurate model to select a number randomly between 1 and 40, six different times, ignoring and re-selecting any time a number is chosen that has already been selected during a previous pick. you must instead remove previously selected numbers from the field to begin with -- so they can never be chosen again.

//initialize and fill array of balls from which to pick
int LottoPool[40];
for (i=0; i<40; i++)
    LottoPool[i]=i+1;  // 1-40

// select and remove six balls at random
int WinningNumber[6];
for (i=0; i<6; i++)
{
    ballSelected = rand() % (40-i) + 1;   // reduce field each time;
    ballIndex = 0;

    do {  
        while(LottoPool[ballIndex] == 0) // if ball is gone...
            ++ballIndex;                 // ... then skip that element
    } while (--ballSelected && ++ballIndex); 

    WinningNumber[i] = LottoPool[ballIndex]; // store ball picked
    LottoPool[ballIndex] = 0;                // remove from element list
}

rather than "re-rolling" an undesired pick, you skip over the index that has already been picked, choosing instead the next sequential element in the lineup

this will work for cards, scrabble tiles, or whatever else you need to pick and remove elements from a finite pool.

.


therefore, it is not an accurate model to select a number randomly between 1 and 40, six different times, ignoring and re-selecting any time a number is chosen that has already been selected during a previous pick. you must instead remove previously selected numbers from the field to begin with -- so they can never be chosen again.

What's wrong with the former approach, jephthah? Certainly you can implement it the way you suggest (the latter approach - removing already picked numbers from the pool so they cannot be picked again), but isn't the other way you mention also valid (once you pick a number, check if it's already been picked. If not, keep it. Otherwise, pick again)? Seems to me that either approach will work.

What's wrong with the former approach, jephthah? Certainly you can implement it the way you suggest (the latter approach - removing already picked numbers from the pool so they cannot be picked again), but isn't the other way you mention also valid (once you pick a number, check if it's already been picked. If not, keep it. Otherwise, pick again)? Seems to me that either approach will work.

of course either way "will work". the point i'm making is that the former method is not a statistically accurate model of the selection process.

if you're trying to investigate lottery distributions or simulate a casino's "Texas Hold'em" table, then your resulting distribution will be inaccurate. (leaving aside, for the moment, the problem with using the "rand()" function and modulus operator, okay? :) )

the reality is, when picking sequential Lotto balls from a container or poker cards from a deck, you don't have a fixed pool that you keep drawing from; on the contrary, the sample size diminishes by one after each and every selection. For instance, the sixth Lotto ball is selected with a 1:35 probability, not a 1:40 probability with a 5:40 probability of each selection needing a "re-do"

furthermore, the latter method is highly inefficient. you have a potential for an undefined number of picks, as each sequential pick necessitates an increased chance of needing one or more re-do's.

Consider shuffling a 416-card casino deck for Blackjack. by the time you get to the last two cards, trying to select between them has a greater than 99.5% chance of picking a card that has already been picked -- each and every time.

.

I agree with you on the inefficiency, disagree with you on the notion that it screws up the desired probability distribution (again, as you point out, leaving aside problems with rand ()). A properly written function will result in every ball having a 6 in 40 chance in being picked, regardless of which method you use. After the first ball is picked, a number has a 1 in 39 chance of being picked second, given that it wasn't picked first, regardless of which method you use. And a 1 in 38 chance of being picked third, given that it wasn't picked first or second. Each individual "roll" gives a 1 in 40 chance, but since certain "rolls" will be thrown out, the odds of a number being picked on the third try ("try" being defined as a number being picked and not thrown out), given that it wasn't picked earlier, increase to be greater than 1 in 40, and will be exactly 1 in 38, so all in all, mathematically, the probabilities are the same regardless of which method you choose.

Comments
i concede.

okay... you might be right. intuitively the former approach seems logically wrong. however, i must admit that in my one semester of Probability and Statistics, i "intuited" my way to a final grade of C+.

and furthermore, for modern PC apps the inefficiency argument is kind of a moot point, since the hit to processing will not be noticed.

but i still think my way is more elegant :P

Here's a mathematical way of thinking about it. You have 40 numbers. Suppose 39 and 40 are the first 2 numbers picked. 1 through 38 are left. What's the probability that 1 will be picked next (I haven't yet learned the Math BB-code, so I'm not going to attempt it)? Let's call that probability p .

Let's define "Draw 0" as the first draw of a number AFTER 39 and 40 are picked (our basic "time 0" starts then).

Let's define:

p(0) = "Probability that 1 is picked on Draw 0"
p(1) = "Probability that 1 is picked on Draw 1"
p(2) = "Probability that 1 is picked on Draw 2"
p(i) = "Probability that 1 is picked on Draw i"

p = p(0) + p(1)  + p(2) + ...

Let's define:

d(0) = "Probability that we make it to draw 0"
d(1) = "Probability that we make it to draw 1"
d(2) = "Probability that we make it to draw 2"
d(i) = "Probability that we make it to draw i"

Draw 0 will definitely happen, so d (0) = 1.
Draw 1 will happen only if Draw 0 is 39 or 40, which is a 2/40 chance, so d(1) = 2/40.
Draw 2 will happen only if Draw 0 is 39 or 40 and Draw 1 is 39 or 40, so d(2) = (2/40)^2.
Draw i will happen only if Draws 0 through i - 1 are 39 or 40, so d (i) = (2/40)^i.

p(0) = (1/40) * d (0) = (1/40) * 1 = (1/40)
p(1) = (1/40) * d (1) = (1/40) * (2/40)
p(2) = (1/40) * d (2) = (1/40) * (2/40)^2
p(i) = (1/40) * d (i) = (1/40) * (2/40)^i

Add 'em all up, using geometric series and you get:

(1/40) * (1 + (2/40) + (2/40)^2  + ...) = 

(1/40) * (1 / (1 - (2/40))) =
(1/40) * (1 / (38/40)) =
(1/40) * (40/38) = 

1 / 38

Hey, Arent you using the wrong formula, I mean the geometric sequence.

a/i-r is the value when a geometric progression goes to infinity.

But we know that i ranges from 1 to 38. so we have a progression of 'n' terms, which is calculated by

a((r^(n+1)-1)/r-1))

http://en.wikipedia.org/wiki/Geometric_progression#Geometric_series

i can go to infinity here. I'm defining "draw" as reaching into the basket and taking a number out and putting it back it in. You could reach in, pull out 40, then put it back in 100 times, then reach in and pick 1 on the 101st draw. The probability of doing that would be:

p(100) = (1/40) * (2/40)^100

where 1/40 is the probability of drawing 1 on the 101st draw, given that there have been 100 failed draws already, and (2/40)^100 is the probability that the first 100 draws would be failures. So i needs to go infinity. The formula is:

p = a * (1 / (1-r))

In this case, a = 1/40 and r = 2/40.


Perhaps the word "attempt" should have been used in place of "draw" in my example, a "draw" being the event of picking and keeping a ball. You would have six "draws" since six balls are needed. For each "draw", you could have billions of attempts. However, in my previous post, I defined "draw" as the act of reaching in and taking a ball, regardless of whether you had to put the ball back. By that definition, there is no limit to the number of draws.

Oh , I am absolutely sorry, I took it other-wise, And basically mistook Lotto for Bingo. However I would like to take back what I have said as I have understood the concept now .

EDIT::

However
If you have meant that the picked number is put back into the area again ,

Here's a mathematical way of thinking about it. You have 40 numbers. Suppose 39 and 40 are the first 2 numbers picked. 1 through 38 are left. What's the probability that 1 will be picked next (I haven't yet learned the Math BB-code, so I'm not going to attempt it)? Let's call that probability p .

You have mentioned that 1 to 38 are left. So isnt that wrong as 1 to 40 are left.

However
If you have meant that the picked number is put back into the area again ,

You have mentioned that 1 to 38 are left. So isnt that wrong as 1 to 40 are left.

This is why language precision is so important when talking about these things. The word "left" is too vague. The discussion was referring to two ways of picking lotto numbers, or "simulating" picking lotto numbers. No person would ever pick a ball, then put it back in. But discussing one method of programming for this, we're assuming that that is what is taking place. So, there will be 40 balls "left" in the basket. 39 and 40, even though they've already been selected, will be placed back in the basket. That's one way of interpreting the word "left", but it wasn't what I meant in that sentence. By "left", I meant that they were eligible to be picked without having to be put back, as in you can say "I've found one that works". In this case, only 1 through 38 fit the bill. Say you have a chalkboard and you are writing down the numbers. 39 and 40 have already been written down. 1 through 38 are "left" in that you potentially will write them down. 39 and 40 won't be written down since they've ALREADY been written down.

This article has been dead for over six months. Start a new discussion instead.