Hi all. I'm writing a program to explain and verify the birthday paradox. I am generating 1000 sets (only 10 to test with) of birthdays, checking for matches, then displaying the results. I'm using srand to seed my generator and rand() to get 23 sets. The problem is 2-fold. 1) It's generating a series of identical negative numbers at the start of the first run. I thought unsigned int was supposed to prevent negatives? 2) It's generating identical sets of numbers. After the first set, there are no more negative numbers but each set is identical. I don't know if this is a matter of generating the sets faster than my clock advances, or if I did something wrong. I've scoured the web and it "looks" like I have it coded correctly.

srand((unsigned int) time (0));

This is in main() after my variable declarations. I only have one call to it.

void GenerateBirthdays(int B[], int SS, int &M)
{
	int j = 0;			//j is loop counter, M is # of Matches

	for (int i = 0; i < NUMBER_OF_SETS; ++i)
	{
		while (B[j] < SS) 
		{
			B[j] = 1 + (rand() % 365);
			++j;
			cout << B[j] << endl;
		}
		SelectionSort(B, SS);

		for (j = 0; B[j] < SS; ++j)
		{
			if (B[j] == B[j+1])
				++M;
			cout << M << endl;
		}
	}
}

This is my function call. My sort function works correctly. My match counter doesn't, but that's something I'll worry about later. If it makes a difference, I'm using a switch statement to create a menu. It also won't let me exit the program without a Run-Time Check Error #2- Stack around the variable 'Birthdays' was corrupted. I'm hoping fixing my srand issue will fix the run time error as well.

you could try

srand(time(NULL));

worked in the past for me but hey i'm not good at this so "pinch of salt".

Edited 5 Years Ago by frogboy77: n/a

I originally coded it that way. I changed it to the unsigned int because i"m getting the negative numbers and I hoped that would get rid of them. I put it back the way you posted it, though, and I'm still getting the same output. This is 2 sets. Every set after the second one is the same as the second.

-858993460
-858993460
-858993460
-858993460
-858993460
-858993460
-858993460
-858993460
-858993460
-858993460
-858993460
-858993460
-858993460
-858993460
-858993460
-858993460
-858993460
-858993460
-858993460
-858993460
-858993460
-858993460
-858993460
1485042948
25 25
293 36
51 47
173 51
346 67
340 95
255 119
336 159
173 172
202 173
304 195
340 201
293 202
304 255
310 286
336 293
342 304
336 310
336 336
346 340
346 342
346 346

I'm not sure with only partial code but on line 10 do you want to be incrementing j before the output on line 11?

Edited 5 Years Ago by frogboy77: n/a

Wow, I feel dumb. LOL That seems to have fixed my negative number issue. Thanks so much for that. It's still not generating random numbers, though.

#include <iostream>
#include <iomanip>
#include <stdlib.h>
#include <time.h>
using namespace std;

These are the libraries I'm using (iomanip is for formatting later). Could the problem be here?

my guess is that you put the

srand((unsigned int) time (0));

in a while, am i correct?, if yes, just move it first line after main.
remember, srand must be called ONLY ONCE(ofc, excluding the cases when you purposely call it more than one time) for the code to work as expected.
other than that i don't know what the problem could be, if this does not solve your problem, post your whole code so we can have a look at it

Edited 5 Years Ago by dospy: n/a

#include <iostream>
#include <iomanip>
#include <stdlib.h>
#include <time.h>
using namespace std;

const int SAMPLE_SIZE = 23;
const int NUMBER_OF_SETS = 10;

void ScreenClear();
void GenerateBirthdays(int B[], int SS, int &M);
void SelectionSort (int List[], int  Last);
inline void Swap (int &A, int &B);


void main()
{
	int Birthdays[SAMPLE_SIZE]; 
	char Choice;
	int Matches = 0;

	srand(time(NULL));

	cout << "Welcome to Erin's Amazing Birthday Paradox Generator!\n\n";
	cout << "\t1) Explain birthday paradox\n";
	cout << "\t2) Check birthday paradox by generating 1000 sets of birthdays";
	cout << "\n\t3) Display one set of 23 birthdays\n";
	cout << "\tE) Exit";
	cout << "\n\nPlease enter your menu selection: ";
	do
	{
		cin >> Choice;

		switch (Choice)
		{
			case '1':
			{
				ScreenClear();

				cout << "\n\nThe birthday paradox can be displayed as follows: ";
				cout << "\n\n\tIf 23 persons are chosen at random, then the "
					 << " chances are more\n\tthan 50% that at least two will "
					 << "have the same birthday!\n\n";

				cout << "Please enter your next menu selection: ";
				break;
			}
			case '2':
			{
				ScreenClear();


				cout <<"Generating 1000 sets of 23 birthdays and checking for "
					 << "matches...\n\n";

				GenerateBirthdays(Birthdays, SAMPLE_SIZE, Matches);

				cout << "Results : " << Matches << " out of 1000 (" 
					 << (Matches / 1000.0) << "%) of the sets contained "
					 << "matching birthdays.\n";
				cout << "===================================================="
					 << "=====================";

				cout << "\n\nPlease enter your next menu selection: ";
				break;
			}
			case '3':
			{
				ScreenClear();
				cout << "\n\nMore random stuff.\n\n";

				cout << "Please enter your next menu selection: ";
				break;
			}
			case ('E' || 'e'):
			{
				cout << "\n\nYou have chosen to exit the program.\n\n";
				cout << "Thank you for using Erin's Amazing Birthday "
					 << "Paradox Generator.  Goodbye!\n\n";
				break;
			}
			default:
			{
				cout << "\n\nYou have selected an invalid entry."
					 << "\nIf you wish to exit the program, please enter E."
					 << "\nOtherwise, please re-enter your selection: ";
				break;
			}
		}
	}
	while (Choice != 'E');
}

void ScreenClear()
{
	const int NUMBER_OF_ROWS = 5;

	for (int R = 1; R <=NUMBER_OF_ROWS; ++R)
		cout << endl;
}

void GenerateBirthdays(int B[], int SS, int &M)
{
	int j = 0;					//j is loop counter, M is # of Matches

	for (int i = 0; i < NUMBER_OF_SETS; ++i)
	{
		while (B[j] < SS) 
		{
			B[j] = 1 + (rand() % 365);
			cout << B[j] << endl;
			++j;
		}
		SelectionSort(B, SS);

		for (j = 0; B[j] < SS; ++j)
		{
			if (B[j] == B[j+1])
				++M;
			cout << M << endl;
		}
	}
}

		
inline void Swap (int &A, int &B)
{
  int Temp= A;
  A = B;
  B = Temp;
}


void SelectionSort (int B[], int  SS)
{
  int i, Start, SubSmall;

  for ( Start = 1; Start < SS; ++Start )  // Sort items 1..Last
    {
    SubSmall = Start;                     //  subscript of smallest elt.

    for ( i = Start; i < SS; i++ )   //  Find subscript of smallest
      if ( B[i] < B[SubSmall] )			  //   elt. in tail end of array
        SubSmall= i;

    Swap(B[SubSmall],  B[Start]);         // Place in correct position

	cout << B[SubSmall] << " " << B[Start] << endl;
    }
}

are you sure this loop is correct? what is it supposed to do?

for (j = 0; B[j] < SS; ++j)
{
    if (B[j] == B[j+1])
        ++M;
    cout << M << endl;
}

from generatebirthdays function
is this loop supposed to count the matching birthdays?
if yes, this is where your code fails, this loop doesn't look to me like doing something logically

edit: also you needn't declare function Swap, you could have used std::swap(as it does the exactly same thing)

Edited 5 Years Ago by dospy: n/a

Yes, that's what it is supposed to do, and I know there's an issue there. But I need to get srand to generate random birthdays before I start picking apart the other issues. What I meant it to do, though, is reset the loop counter to 0, then go element by element and compare. It doesn't, so I did something wrong. code will

line 108, again,

while (B[j] < SS)

try replacing with

for(j = 0; j < SS; ++j)

in that while basically you check if B[j](unassigned value) is < 23(pretty slim chances)
so almost none of the array elements get initialized, that's why your program is printing negative values, it just prints garbage

Edited 5 Years Ago by dospy: n/a

I think that fixed it! I'm looking through the new output and it looks like every set is different. Thank you so much for the help. I've been staring at this code for so long that it was starting to not make sense anymore. <3

your welcome

>> I've been staring at this code for so long that it was starting to not make sense anymore.
don't worry, happened to all of us(i guess), at least to me.
when i got so frustrated about my code failing i just have had a brake for my brain to think logical again; remember it's not good to code when you are angry or under pressure, this way you can't focus

Edited 5 Years Ago by dospy: n/a

Yep, that definately fixed the issue. Also, I have to do the swap function call. We're not far enough to do the one you showed me.

That loop is still a problem. I know it's a logic error. What I want it to do is search a set, and if it finds a match, increment the match counter and then exit the set. I don't need it to find every match in the set.

If I do a for-loop, it will find all the sets. If I try to use a while-loop, it doesn't always work right. I tried adding a break statement to the for-loop. I know there has to be a better way than that, and it doesn't always work, either. Still plugging away at it.

i am not sure i understood what you want, if i got it right, the thing goes more complicated

this way you find ALL matches in the set

int matches;
for(j = 0; B[j] <= SS; ++j)
{
    matches = 0;    
    for(int k = j; k <= SS; k++)
    {
        if(B[j] == B[k])
            matches++;
    }
    if(matches > 1)
        cout << matches << " entries of the number " << B[j] << "in the set" << endl;

    matches = 0;
}
/*
note that this will output the pairs of numbers more than one time.
for example we have the set: 1, 10, 10, 10
when the main loop arrives at the first 10 it'll output
'3 entries of the number 10 in the set'
and than goes to the second one, so it'll print again and again...

if you want only one time you'll have to implement a function for erasing all elements equal to the parameter from the array
something like this:

void EraseEl(int a[], int el, unsigned int size)
{
// code here for erasing all elements equal with 'et' from the vector...
}
*/

from here you can adapt it to your code

Edited 5 Years Ago by dospy: n/a

Yeah, I was frustrated so I was ranting about it to my boyfriend and I think I figured it out. LOL It's not elegant, but what I did was pretty much what you have above, except matches became x. If x > 0, ++matches. I let it go ahead and find all the matches, but then it only increased the actual matches variable one time regardless of how many matches each set contained.

This question has already been answered. Start a new discussion instead.