# Thread: match probability is correct for a full match but not for a partial match

1. ## match probability is correct for a full match but not for a partial match

I created a C program that provides stats on random number (lotto) matches. The calculated probability of a full match equals the programs average output for a full match, but a partial match, like matching 3 out of the 6 numbers, is always significantly higher for the program than the calculated probability.

example: 6/49 match 6 probability is around 1 in 13.9 million, my program consistently has an average around 13-14 million.

example: 6/49 match 3 probability is around 1 in 57, my program consistently has an average of mid 900s.

My compiler is MinGW. I am using the 64-bit version of Mersenne Twister pseudorandom number generator to generate my random numbers.

The program flow is as follows:
- The user inputs a max (ex: 49), a pick amount (ex: 6), a match amount(ex: 3), and the number of draws to perform
- The user enters 3 random numbers (ex: 7 18 44)
- The program then generates a random set of 6 numbers (checking for duplicates) from the max of 49, and stores them in an array
- Once the program has 6 numbers with no duplicates, it performs a match check to see if the user's 3 numbers match any of the computer's six numbers
- A loop counter is increased by 1 for each match check. If there is no match, the computer picks another set of 6 random numbers and checks for a match
- this process repeats until the computer's 6 numbers contains the 3 numbers that the user entered
- the program outputs a running average of how many attempts it took to match 3 out of the 6 computer picked numbers
- the match-attempts and switch statement is something new that I added, the probability problem existed prior to it

Is there a mistake in my logic while generating the random numbers and checking for a match? I have dissected the code numerous times, and I cannot see what the problem might be.

Code:
```#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <time.h>

#include <random2.h> //place in C:\MinGW\include folder

#define ARRAYSIZE 100

//typedef enum {false, true} bool;
bool checkArray(int currentIndex, int number, int array[]);
bool checkMatch(int arrayInput[], int arrayRandom[], int picks, int amttomatch);
void sort( int array[], int picks);
void print(int array[], int picks);
void switch_print(double loop, double average, double DrawLoopCount, double draw_span);
void printToFile(int array[], double loop, bool match, int picks, int amttomatch);

int roll (int max);

int main() {
bool duplicate;
bool match;
char quit, rml_condition;
int indexR, indexI, input, pick, max;
int inputNumbers[ARRAYSIZE], randomNumbers[ARRAYSIZE], picks, amttomatch, reachMatchLoop;
double loop=0, total=0, average=0, draws=0, DrawLoopCount=1, previous_DrawLoopCount=0, reachMatchLoop_count=0;
double draw_span=0, draw_span_total=0, draw_span_avg=0;
FILE *fp1;// File pointer

//seed random number generator rand
time_t t;
//srand((unsigned) time(&t));

//seed random number generator in random2.h
init_genrand64(time(&t));

printf("Lottery Probability\n\n");
while(quit != 'q'){
//User inputs array of numbers
printf("Enter a max number: ");
scanf("%d", &max);

printf("Set match-attempts (ex. 16 means track amount of times it took 16 or more attempts to reach a match [enter 0 to skip this]: ");
scanf("%d", &reachMatchLoop);

if(reachMatchLoop != 0){
while(rml_condition != 'g' && rml_condition != 'l' && rml_condition != 'e'){
_flushall();
printf("(g)reater than, (l)ess than, or (e)qual to %d: ", reachMatchLoop);
//scanf("%c",&rml_condition);
rml_condition = getchar();
printf("\n");
}
}

printf("How many numbers (from %d) to pick: ", max);
scanf("%d", &picks);

printf("How many numbers to match out of the %d picks: ", picks);
scanf("%d", &amttomatch);

printf("Enter number of draws to perform: ");
scanf("%lf", &draws);

//User inputs random numbers in range of max in amount of numbers to match
printf("\nInput %d numbers from 1 - %d\n", amttomatch, max);
for(indexI=0; indexI<amttomatch; indexI++){
inputNumbers[indexI]=0;
}
//print(inputNumbers,ARRAYSIZE);

for(indexI=0; indexI<amttomatch; indexI++){
do{
printf("Entry%d: ",indexI+1);
scanf("%d", &input);
duplicate = checkArray(indexI,input,inputNumbers);
}while((input<1 || input > max) || duplicate);
inputNumbers[indexI]=input;
}
printf("\n");

//Computer generates array of numbers with no duplicates, and checks picks for a match with input
for(DrawLoopCount=1; DrawLoopCount<=draws; DrawLoopCount++){
match = false;
while(!match){
for(indexR=0; indexR<picks; indexR++){
randomNumbers[indexR]=0;
}
for(indexR=0; indexR<picks; indexR++){
do{
pick = roll(max);
duplicate = checkArray(indexR,pick,randomNumbers);
//printf("%2.0f | %d ", loop,pick);
//printf("dup=%s\n", duplicate ? "true" : "false");
}while(duplicate);
randomNumbers[indexR]=pick;
//printf("%2.0f R=%d\n", loop,pick);
}

match = checkMatch(inputNumbers, randomNumbers, picks, amttomatch);
loop++;
//print(randomNumbers,picks);
//printf("%2.0f ", loop);
//printf("match=%s\n", match ? "true" : "false");

//printToFile(randomNumbers,loop,match,picks,amttomatch);
}
total+=loop;
average = total/DrawLoopCount;

switch(rml_condition) {
case 'g':
if(loop >= reachMatchLoop){
reachMatchLoop_count++;
draw_span = DrawLoopCount-previous_DrawLoopCount;
draw_span_total+=draw_span;
draw_span_avg = draw_span_total/reachMatchLoop_count;

switch_print(loop, average, DrawLoopCount, draw_span);

printf ("Draw Span Avg from %2.0lf attempts per match >= %d: %4.2lf  |  \n", reachMatchLoop_count, reachMatchLoop,draw_span_avg);
previous_DrawLoopCount = DrawLoopCount;
}
break;

case 'l':
if(loop <= reachMatchLoop){
reachMatchLoop_count++;
draw_span = DrawLoopCount-previous_DrawLoopCount;
draw_span_total+=draw_span;
draw_span_avg = draw_span_total/reachMatchLoop_count;

switch_print(loop, average, DrawLoopCount, draw_span);

printf ("Draw Span Avg from %2.0lf attempts per match <= %d: %4.2lf  |  \n", reachMatchLoop_count, reachMatchLoop,draw_span_avg);
previous_DrawLoopCount = DrawLoopCount;
}
break;

case 'e':
if(loop == reachMatchLoop){
reachMatchLoop_count++;
draw_span = DrawLoopCount-previous_DrawLoopCount;
draw_span_total+=draw_span;
draw_span_avg = draw_span_total/reachMatchLoop_count;

switch_print(loop, average, DrawLoopCount, draw_span);

printf ("Draw Span Avg from %2.0lf attempts per match = %d: %4.2lf  |  \n", reachMatchLoop_count, reachMatchLoop,draw_span_avg);
previous_DrawLoopCount = DrawLoopCount;
}
break;

default:
printf ("Attempts: %10.0lf | ", loop);
printf ("Average: %11.2lf | ", average);
printf ("Draw Counter: %0.0lf\n", DrawLoopCount);
break;
}

loop=0;
}

fp1 = fopen("matchAnyPartial.txt", "a");
fprintf (fp1,"%d/%-4d", picks, max);
fprintf (fp1,"Average Attempts: %11.2lf   ", average);
fprintf (fp1,"Loop Count: %4.0lf ", DrawLoopCount-1);
fprintf (fp1,"Match Picks: %2d\n", amttomatch);
fclose (fp1);

printf("\n");
printf("Your Numbers:");
sort(inputNumbers,amttomatch);
print(inputNumbers,amttomatch);

printf("\n");
printf("Matched Numbers %d of %d:", amttomatch, picks);
sort(randomNumbers,picks);
print(randomNumbers,picks);

printf("\n");

loop=0;
total=0;
average=0;
reachMatchLoop=0;
reachMatchLoop_count=0;
DrawLoopCount=1;
previous_DrawLoopCount=0;
rml_condition='\0'; //clear char variable
draw_span=0;
draw_span_total=0;
draw_span_avg=0;

printf ("Hit enter to go again.  Hit 'Q' to exit\n");
_flushall();
quit = getchar();quit=tolower(quit);
}
return 0;
}

/* Compare input array with rand array for a match */
bool checkMatch(int arrayInput[], int arrayRandom[], int picks, int amttomatch){
int indexR=0, indexI=0, amount=0;
bool match;
//printf("Check for match\n");
//print(arrayInput,amttomatch);
//printf("\n");
//print(arrayRandom,picks);
for(indexR; indexR<picks; indexR++){
for(indexI; indexI<amttomatch; indexI++){
if (arrayRandom[indexR] != arrayInput[indexI]){
//printf("%d | %d\n", arrayRandom[indexR], arrayInput[indexI]);
match = false;
} else{
//printf("%d = %d\n", arrayRandom[indexR], arrayInput[indexI]);
amount++;
}
}
//printf("match=%s\n", match ? "true" : "false");
//printf("dup=%s\n", duplicate ? "true" : "false");
indexI=0;
}

if(amount==amttomatch){
match = true;
}
//printf("%d | %d | ", amount, amttomatch);
//printf("match=%s\n", match ? "true" : "false");
return match;
}

/* Check an array while being created to prevent duplicate entries */
bool checkArray(int currentIndex, int number, int array[]){
int index;
for(index=0;index<=currentIndex;index++){
if (array[index]==number){
//printf("%d = %d\n", array[index], number );
return true;
}
}
return false;
}

void print(int array[], int picks){
int index = 0;
puts("");
for(index; index<picks; index++){
printf("Number%d: %d\n",index+1,array[index]);
}
}

void switch_print(double loop, double average, double DrawLoopCount, double draw_span){
printf ("Attempts: %10.0lf  |  ", loop);
printf ("Overall Average: %11.2lf  |  ", average);
printf ("Draw Counter: %10.0lf  |  ", DrawLoopCount);
printf ("Draw Span: %10.0lf  |  ", draw_span);
}
void printToFile(int array[], double loop, bool match, int picks, int amttomatch){
int index = 0;
FILE *fp2;
//puts("");
fp2 = fopen("matchAnyPartialAttempts.txt", "a");
fprintf (fp2,"Attempts: %.0lf\n", loop);
fprintf (fp2,"Match: %d\n", match);
fprintf (fp2,"Match Picks: %2d\n", amttomatch);
for(index; index<picks; index++){
fprintf(fp2,"Number%d: %d\n",index+1,array[index]);
}
fprintf (fp2, "\n");
fclose (fp2);
}

void sort( int array[], int picks){
int index, temp, pass, limit;
index = picks;
limit = picks-2;
for (pass=1;pass<=picks-1;++pass){
for(index=0;index<=limit;++index){
if (array[index]>array[index+1]){
temp=array[index];
array[index]=array[index+1];
array[index+1]=temp;
}
}
--limit;
}
}

int roll (int max) {
int rmax;
//rmax = rand()%max+1;
rmax = genrand64_int63()%max+1;
return rmax;
}``` 2. I haven't looked at your code, but remember that those odds (1 in 57) are for a match of 3 numbers in 6, so the user should still enter a ticket of 6 numbers. If any 3 of them match the generated number then they've matched 3. Since 6 choose 3 is 20, it's understandable that your probability is about 20 times too low.

Here's a little program that gets the correct probabilities.
Code:
```// gcc -std=c99 -Wall -W -pedantic -O3 lotto.c
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>

#define Reps     10000000
#define MaxNums  49
#define PickNums 6

int main() {
srand(time(NULL));
int ticket[PickNums] = {1, 4, 15, 23, 39, 42}; // actually 2, 5, 16, etc.
int match[PickNums + 1] = {0};
int draw[MaxNums];
for (int rep = 0; rep < Reps; ++rep) {
//if (rep % 1000000 == 0) printf("%d\n", rep); // for long runs
memset(draw, 0, MaxNums * sizeof *draw);
for (int i = 0; i < PickNums; ) {
int r = rand() % MaxNums;
if (!draw[r]) {
draw[r] = 1;
++i;
}
}
int cnt = 0;
for (int i = 0; i < PickNums; ++i)
if (draw[ticket[i]])
++cnt;
++match[cnt];
}
for (int i = 0; i <= PickNums; ++i)
printf("%d. %10d %12.2f\n", i, match[i], (double)Reps / match[i]);
return 0;
}```
Output from a run of a hundred million reps:
Code:
```0.   43597233         2.29
1.   41302578         2.42
2.   13239268         7.55
3.    1762724        56.73
4.      96336      1038.03
5.       1854     53937.43
6.          7  14285714.29``` 3. >>for a match of 3 numbers in 6, so the user should still enter a ticket of 6 numbers
That is what I was missing. I was not making the other 3 possible numbers available to be checked for a match. I edited the code and now the probabilities for partial matches equal the calculated probability.

Thanks john.c Popular pages Recent additions #### Tags for this Thread

int, match, numbers, probability, random numbers 