Question about a program

Hi guys,

I'm new to this website, and fairly new in C++. As of now, I'm also trying to write a program for my class that spits out random numbers, and when there's a back2back evens, it counts how many tries it took to get that result. For example, if the program spits out four random numbers, like 4, 3, 10, 18, it'll stop and record that it took four random numbers to get back2back evens. It does this until it finds a million successful back2backs, and it uses the numbers 1-100, inclusively. Obviously, the least amount of tries would be 2. I think my biggest trouble is trying to return a vector. Here is the code that I have (it is completed for the most part):

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
32
33
34
35
36
37
38
39
40
#include <iostream>
#include <vector>
#include <time.h>

using namespace std;
const int maxDraw = 99;
const long int ranMax = 1000000;

vector<int> DrawArray(vector<int> Draw);

int main()
{
	vector<int> randomDraw;
	DrawArray(randomDraw);
	
	return 0;
}

vector<int> DrawArray(vector<int> Draw)
{
	int num[maxDraw];
	int i = 0;
	int counter = 0;
	srand((unsigned)time(NULL));

	for (counter; counter <= ranMax; counter++)
	{
		while (num[i] != 0 && num[i-1] != 0)
		{
			num[i] = rand() % 100 + 1;
			num[i] = num[i] % 2;
			if (num[i] == 0 && num[i-1] == 0)
			{
				Draw[i]++;
			}
			i++;
		}
	}
	return Draw;
}
I think my biggest trouble is trying to return a vector

It looks like you just want to pass the vector by reference which you can do like this:

void DrawArray(vector<int>& Draw);

However, the biggest trouble I see is the logic within DrawArray. Whatever it's doing, it's not keeping track of the number of tries for each of the one million back to backs. You should have an array of 1000000 ints somewhere that keeps track of the counts (or you could print out the counts as they occur but I don't know if you're allowed to do that for this question, depending on what they mean by "stop and record").

Your "counter" loop does one-million-and-one iterations, not one million.

Your num array has room for 99 elements though you don't reset i back to zero, so there will be an array out of bounds eventually, not to mention the array out of bounds that happens right away when you try to do

num[i - 1]

when i is zero. You don't really need to keep track of the random numbers anyway, just the previous number and a counter storing how many numbers were used so far would suffice.

You also need to give your vector a starting size since accessing it like you're doing is also causing an array out of bounds.
Last edited on
So if I used

void DrawArray(vector<int>& Draw);

What would it look like if I were to call the function? Another question is how would I return it to the main function? And would it return that vector?
If you had

void DrawArray(vector<int>& Draw);

as the function signature, then you would call it just like you already are:

1
2
vector<int> randomDraw;
DrawArray(randomDraw);


Another question is how would I return it to the main function? And would it return that vector?

If you called the function like the above, then the vector is passed by reference, meaning that whatever changes you make to it within DrawArray will be reflected in the vector you passed to it.
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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
#include <iostream>
#include <vector>
#include <time.h>

using namespace std;
const int maxDraw = 100;
const long int ranMax = 1000000;

void DrawArray(vector<int>& Draw);

int main()
{
	vector<int> randomDraw(maxDraw);
	DrawArray(randomDraw);
	
	return 0;
}

void DrawArray(vector<int>& Draw)
{
	int num[ranMax] = {0};
	int i;
	int counter = 0;	

	for (counter; counter <= ranMax; counter++)
	{
		i = 0;
		srand((unsigned)time(NULL));
		num[0] = rand() % 100 + 1;
		num[1] = rand() % 100 + 1;
		
		if (num[0] % 2 == 0 && num[1] % 2 == 0)
		{
			Draw[0]++;
		}
		else
			while (num[i + 2] != 0 && num[i + 1] != 0)
			{
				num[i + 2] = rand() % 100 + 1;
				
				if (num[i + 2] % 2 == 0 && num[i + 1] % 2 == 0)
				{
					Draw[i + 1]++;
				}
				i++;
			}
	}
}


I tried fixing it a bit more, but to no avail... I did try passing by reference, but I'm still not sure if it needs to have a "return". I also fixed the barrier problem you were noting at earlier. I should explain a bit more what I'm trying to do though.

So ultimately, the vector randomDraw is what's keeping count of how many times back2back evens pop up. The least amount of tries would be 2, while there can be infinitely many tries to get a back2back double result. So the first element would be "2 tries", and so on so forth.

What the function "DrawArray" does is that it'll produce random integers, divide them all by 2, and if the most recent integer and the previous integer has a remainder of 0, it will record it to one of Draw's elements(the vector Draw being randomDraw, but you probably know that), depending on how many tries it took. The first loop is what will make it go through the one million trials, while the second loop within the first loop just produces the random integers. Then I would like to return that vector of recorded tries (I highly doubt it'll take 20 or more tries to get back2back evens). With that, I can create a new function to print out the result. That, I can do, but I just can't seem to figure out how to return the vector. And if the syntax for that is right, then something must be wrong in my loop.

Thanks much for the help, it's appreciated.
In terms of "returning" your vector, the way you have it is fine. When an object is passed by reference, no return statement is necessary. The caller's object gets changed as the called function changes the object.

int num[ranMax] = {0};
Again, you don't need to keep track of all the random numbers you generate, only the previous two. Thus you don't need this array of one million ints. I would keep track of two numbers, for example, int randomNums[2];, where randomNums[0] would store the random number generated two tries ago and randomNums[1] would store the previously generated random number.

In terms of your loop, you should be terminating when num[i + 2] and num[i + 1] modulo 2 are zero. Right now you're just checking if the elements themselves are zero, which of course is not what you want.
Last edited on
Alright so I did some modifications. Now the program compiles runs fine and doesn't crash... however, I'm not getting the output I want. When I try printing out the result for a total of 2 tries, I just get 0, when it should be ~400,000. Here's the fixes:
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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
#include <iostream>
#include <vector>
#include <time.h>

using namespace std;
const int maxDraw = 100;
const long int ranMax = 1000000;

void DrawArray(vector<int>& Draw);

int main()
{
	vector<int> randomDraw(maxDraw);
	DrawArray(randomDraw);
	
	cout << randomDraw[0] << endl;
	return 0;
}

void DrawArray(vector<int>& Draw)
{
	int num[2];
	int i;
	int counter = 0;	

	for (counter; counter <= ranMax; counter++)
	{
		i = 1;
		
		srand((unsigned)time(NULL));
		num[1] = rand() % 100 + 1;
		num[0] = rand() % 100 + 1;
		
		if (num[1] % 2 == 0 && num[0] % 2 == 0)
		{
			Draw[0]++;
		}
		else
			while (num[1] % 2 != 0 && num[0] % 2 != 0)
			{
				num[1] = rand() % 100 + 1;
				num[0] = rand() % 100 + 1;
				
				if (num[1] % 2 == 0 && num[0] % 2 == 0)
				{
					Draw[i]++;
				}
				i++;
			}
	}
}
You should only call srand once. Call it at the beginning of main. With the way you have it, srand is called repeatedly, and since it's happening so fast, it's probably being seeded with the same time value thus you're receiving the same random numbers.

I see that you're only keeping track of two random numbers at a time, which is good, however you're not doing it quite right. You generate pairs of numbers at a time when you really should be generating one at a time. I'll show you what I had in mind in pseudo code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
//generate two random numbers
num[0] = rand(); num[1] = rand();

count = 2;

//check if both num[0] and num[1] are even. If so, count = 2 and start a new attempt

//Otherwise, continue the following until num[0] and num[1] are even:

//increment the count
count++;

//overwrite the number we generated two tries ago
num[0] = num[1];

//generate a new random number
num[1] = rand();


Keeping track of the counts the way you do it in the Draw/randomDraw vector is actually quite clever. However, be sure that you handle if i ever reaches 100 (it's unlikely I know but it's a loophole in your algorithm). Consider growing the Draw vector if this case is reached. You could also output the counts to the console or a file if you're allowed.
To answer your first question, you can return vectors just like other objects:

1
2
3
4
5
6
7
8
9
10
11
12
vector<int>  DrawArray() { 
    vector<int> result(maxDraw);
...
    return result;
}

...

int main()
{
	vector<int> randomDraw = DrawArray();
	


There is no need for this "out-parameter" stuff.
I feel like there's something wrong with my loop now... even though I can't seem to find anything wrong with it. When I do try to output the counts to the console, for 2 tries it's getting ~250,000 (which comparing it to my classmates', isn't close. That's what they got for 3 tries). On top of that, when I do try to output for three or more tries, it just displays 0. Here are my changes to the second function:
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
32
33
void DrawArray(vector<int>& Draw)
{
	int num[2];
	int i;
	int counter = 1;	

	for (counter; counter < ranMax; counter++)
	{
		i = 1;		

		num[0] = rand() % 100 + 1;
		num[1] = rand() % 100 + 1;
		
		if (num[0] % 2 == 0 && num[1] % 2 == 0)
		{
			Draw[0]++;
		}
		else
		{
			while (num[0] % 2 != 0 && num[1] % 2 != 0)
			{
				num[0] = num[1];
				num[1] = rand() % 100 + 1;
				if (num[0] % 2 == 0 && num[1] % 2 == 0)
				{
					Draw[i]++;
				}

				i++;
			}
		}
	}
}
I can see something wrong with this condition:

while (num[0] % 2 != 0 && num[1] % 2 != 0)

This says "keep generating numbers while both numbers are odd". You want something more like "keep generating numbers while they're not both even".
I thought that that's what I wanted. While one or both numbers are odd, repeat the loop. Once that statement is false, however (when num[0] and num[1] are even, or equal to 0) it will terminate the loop and start a new trial.
While one or both numbers are odd

Exactly. Your statement says "while both numbers are odd". That doesn't handle the case when one of the numbers is odd.

You want this instead:

while (num[0] % 2 != 0 || num[1] % 2 != 0)

Notice the 'or'.

When I do try to output the counts to the console, for 2 tries it's getting ~250,000 (which comparing it to my classmates', isn't close. That's what they got for 3 tries).

Actually, the ~250,000 for 2 tries makes sense. Given two numbers, the probability that both of them are even is 1/4 ( P(Num1 is even) x P(Num2 is even) = 1/2 x 1/2 = 1/4). From this we would think that a quarter of the attempts would produce two evens right away (and 250,000 is a quarter of one million).
Last edited on
Topic archived. No new replies allowed.