I am trying to teach myself C++ in preparation for graduate school this coming fall but I am having some trouble with this birthday paradox problem. My code seems to run ok but I am not getting the correct output. If anyone has any suggestions please let me know.
#include <cstdlib>
#include <iostream>
#include <ctime>
using namespace std;
int main()
{
srand(time(NULL));
const int trials = 100000;
int birthdays[50];
int numMatches;
for(int i = 2; i <= 50; i++)
{
numMatches = 0;
for(int j = 1; j <= trials; j++)
{
for(int k = 1; k <= i; k++)
{
birthdays[k] = (rand() % 365) + 1;
}
int m = 1;
bool matched = false;
while(m < i && !matched){
int n = m + 1;
while(n <= i && !matched){
if(birthdays[m] == birthdays[n]){
numMatches++;
matched = true;
}
n++;
}
m++;
}
}
cout << "Probability of " << i << " people in a room sharing a birthday is \t"
<< ( float(numMatches) / float(trials) ) << endl;
}
}
Your code is not computing the probability of two people in a room of 50 sharing a birthday. There's several bugs, mostly with indexing, but here's the biggest issue:
for(int j = 1; j <= trials; j++) {
// assigns a random birthday to the first i people (should be 0 indexed)
for(k = 1; k <= i; k++)
birthdays[k] = (rand() % 365) + 1;
// Does *exactly* the same thing as the previous loop, overwriting what
// the initial loop did. Useless code
for(m = 1; m <= i; m++)
birthdays[m] = (rand() % 365) + 1;
// At this point, m = k = i + 1. Here you check if
// the i + 1st array value has the same b-day. It will, because they're
// the same thing. Note you never set the i + 1st value so the loops
// above did nothing
if(birthdays[k] == birthdays[m])
++numMatches;
}
So what you've got here is something like:
Perform 48 iterations of the following (from your first loop which goes from 2 to 50: no idea where those values came from)
For each of those 48 iterations, perform 10k iterations of:
assign a bunch of random stuff to an array overwriting stuff
Ignore the values you wrote in the array, do a comparison that's always true and increment numMatches by 1
Consider what's going on here:
for(int j = 1; j <= trials; j++) {
for(k = 1; k <= i; k++)
birthdays[k] = (rand() % 365) + 1;
for(m = 1; m <= i; m++)
birthdays[m] = (rand() % 365) + 1;
if(birthdays[k] == birthdays[m])
++numMatches;
}
You go through i birthdays and assign a random number, then you go through the same i birthdays and assign them a new random number. Then you try to find a match for just one value of k and m (which both happen to equal i+1, which isn't one of the values set!).
My suggestion is to break the problem down into smaller units that will make it easier to figure out how to code - here are the functions I would try to write.
/* randomizeBirthdays()
* Put n random birthdays into the pre-allocated array birthdays.
* birthdays must of course be of length <= n.
*/
void randomizeBirthdays(int * birthdays, int n);
/* hasMatchingBirthdays()
* Check if birthdays array has two people with the same birthday
* in the first n entries.
* Return value is boolean.
*/
bool hasMatchingBirthdays(int * const birthdays, int n);
/* probabilityOfMatch()
* Calculate the probability that at least 2 out of n people will
* have the same birthday, using nTrials number of trials.
* Return value is double.
*/
double probabilityOfMatch(int n, int nTrials);
If you break it down like this it becomes easier to write and easier to troubleshoot.
As I said in comments already:
I think your aim is to test if 2 people in room of 2-50 people share
birthday, not if 2-50 people share birthday as you say in output. And
that's 2 people out of 23 have 50.7%, not 24.
I completely reworked your code:
#include <iostream>
#include <cstdlib>
#include <ctime>
using namespace std;
#define DAYS_IN_YEAR 365
#define TRIALS 10000
void clearArray (bool * array)
{
for (int i = 0; i < DAYS_IN_YEAR; i++)
array[i] = false;
}
int main()
{
srand(time(NULL));
bool birthdays[DAYS_IN_YEAR]; //we are trying to hit same day in year twice
int r, numMatches;
for(int i = 2; i < 50; i++)
{
numMatches = 0;
for(int j = 0; j < TRIALS; j++)
{
clearArray(birthdays);
for(int k = 0; k < i; k++)
{
r = rand() % DAYS_IN_YEAR; // == 0-364
if (birthdays[r])
{
numMatches++;
break; // 2 people already have same birthdays here
}
birthdays[r] = true;
}
}
cout << "Probability of 2 people having same birthday in room of " << i << " people is "
<< (float)numMatches / TRIALS << endl;
}
}
Output:
Probability of 2 people having same birthday in room of 23 people is 0.516
I think the code must be something like this.
#include <cstdlib>
#include <iostream>
#include <ctime>
using namespace std;
int main() {
srand(time(NULL));
int birthdays[10000][50];
int numMatches;
int trials=10000,check;
for(int n=0;n<trials;n++)
{
for(int j=0;j<50;j++)
{
birthdays[n][j]=rand()%365+1;
}
}
for(int i=2;i<=50;i++)
{
numMatches=0;
for(int n=0;n<trials;n++)
{
check=1;
for(int j=0;j<i;j++)
{
for(int k=j+1;k<=i;k++)
{
if(birthdays[n][j]==birthdays[n][k]&&check)
{
numMatches++;
check=0;
}
}
}
}
cout << "Probability of " << i << " people in a room sharing a birthday is \t" <<
(static_cast<float>(numMatches) / (trials)) << endl;
}
}
Related
Ive been working on this problem for a while but every time I submit it I get the wrong answer, however when I input sample cases I seem to produce the right answer. Could anyone help me out here?
The problem can be found on this site: http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&category=3&page=show_problem&problem=36
The code itself:
#include <vector>
#include <stdio.h>
#include <iostream>
#include <algorithm>
using namespace std;
long find_cycle_length(long b)
{
// Finds the max cycle of b
long max_cycle = 1;
while (b != 1)
{
if (b % 2 != 0)
{
b = (3 * b) + 1;
++max_cycle;
}
else if (b % 2 == 0)
{
b /= 2;
++max_cycle;
}
}
return max_cycle;
}
long find_max_cycle(vector <long>& b)
{
vector <long> temp;
for (int i = 0; i < b.size(); ++i)
{
long buffer = b[i];
temp.push_back(find_cycle_length(buffer));
}
long max_cycle = *max_element(temp.begin(), temp.end());
return max_cycle;
}
int main()
{
long i = 0; // First number
long j = 0; // Second number
long size = 0; // Determines the size of the vector buffer
long counter = 0; // Used to fill buffer
cin >> i >> j;
if (j > i) {
size = (j - i) + 1;
counter = i;
}
else if (i > j) {
size = (i - j) + 1;
counter = j;
}
else if (i == j)
{
size = 1;
counter = i;
}
vector<long> buffer(size); // Used to store all numbers i to j
for (int x = 0; x < buffer.size(); ++x) // fill buffer
{
buffer[x] = counter;
++counter;
}
cout << i << " " << j << " " << find_max_cycle(buffer) << endl;
return 0;
}
I think you may be misunderstanding the instructions. The sample input isn't
1 10
but
1 10
100 200
201 210
900 1000
You don't have a while loop that lets the user give you more than one line of input -- your program quits after one. Why don't you make that change -- let the user keep putting in new lines of input till giving you an end-of-file (or -- it works out the same for coding -- accept all lines of input from an input file redirected to standard input) -- and see if you get an OK?
Oh, I see molbdnilo suggested this in the first comment. Anyway: he's right.
This question already has answers here:
'foo' was not declared in this scope c++
(3 answers)
Closed 6 years ago.
I am getting an error that breed is not declared in scope even though it is right below the fucntion. What is wrong?
The exact error is: prog.cpp: In function ‘void best(std::string*)’:
prog.cpp:131:15: error: ‘breed’ was not declared in this scope
breed(bestRats)
#include <iostream>
#include <sstream>
#include <vector>
#include <math.h>
#include <map>
#include <string.h>
#include <queue>
#include <regex>
#include <bitset>
#include <stdlib.h>
#include <climits>
// #include "dungeonrats.cpp"
using namespace std;
/*
Finds the maximum integer in an array of integers.
Size is the size of the given array.
*/
int getMax(int* numbers, int size) {
int maximum = INT_MIN;
for (int i = 0; i < size; i++) {
if (numbers[i] > maximum) maximum = numbers[i];
}
return maximum;
}
int getMaxi(int* numbers, int size) {
int maximum = INT_MIN;
int maxi;
for (int i = 0; i < size; i++) {
if (numbers[i] > maximum) {
maximum = numbers[i];
maxi = i;
}
}
return maxi;
}
/*
"randomly" generates a new maze (but is it REALLY random?)
aim is 65% empty tiles
10% food tiles
10% obstacles
15% pits
*/
string getNewMaze(string mapseed) {
string maze = mapseed.substr(6); // get everything except the 25:25:
for (int i = 0; i < 626; i++) {
int percentile = rand() % 100; // from 0 to 99
if (percentile < 65) {
maze[i] = '.';
}
else if (percentile >= 65 && percentile < 75) {
maze[i] = '$';
}
else if (percentile >= 75 && percentile < 85) {
maze[i] = '*';
}
else maze[i] = 'X';
}
return maze;
}
/*
A function used to print how many of each kind of tile
exist in the maze.
*/
void testFrequency(string mapseed) {
int numEmpty = 0;
int numFood = 0;
int numObs = 0;
int numPit = 0;
for (int i = 0; i < 626; i++) {
if (mapseed[i] == '.') {
numEmpty++;
}
if (mapseed[i] == '$') {
numFood++;
}
if (mapseed[i] == '*') {
numObs++;
}
if (mapseed[i] == 'X') {
numPit++;
}
}
cout << "Number of empty tiles is " << numEmpty << endl;
cout << "Number of food tiles is " << numFood << endl;
cout << "Number of obstacles is " << numObs << endl;
cout << "Number of pits is " << numPit << endl;
}
/*
Returns an array of size 2 containing the best two rats.
*/
void best(string r[]) {
// r is the array of five rat genomes
//int moves = simulator(mapseed, genome, start_row, start_col);
int* ratMoves = new int[5]; // array that stores how long each rat lasted
int maxIndex = 0;
int max = INT_MIN;
string originalMapseed = "25:25:..$.$.X.............X....$X.X*..X$..X...*X$..$...X$.$......X.$.X...XX.$.X*.*.*..X..X.**.......X..$$$...........XX.....................$...X...*.$..X..$X..........$.*..X.....$.X..$*.$X......$...X.*X$......$.**.X.X..XX$X..*....*..X.X....$...X...X........$.X....$...*...X$*........X..$*$$......$$...$*..X.$.$......$.$.$...$..X.*.....X..$......$.XX*..X.$.X......X$*.**.....X*...$..XX..X.....$....X....X...X....X.$X$..X..........$...*.X$..X...$*...........*....XXX$$.$.$..*$XX..XX..*.....$......X.XX$..$$..X$.XX.$$..X.*..*......X......$..$.$$..*...X.........$X....$X.$$.*.$.$.$..**.....X.$.$X.*.$.........$**..X.X.X$X.$.*X.X*..$*.";
for (int i = 0; i < 5; i++) {
string mapseed = getNewMaze(originalMapseed);
int sumTurns = 0;
for (int k = 0; k < 10; k++) {
string mapseed = getNewMaze(originalMapseed);
// sumTurns += simulator(mapseed,r[i],12,12); // uncomment this line once in correct file
}
ratMoves[i] = sumTurns / 10; // average of rat's performance
// over 10 random maps
if (ratMoves[i] > max) { // find the best
max = ratMoves[i];
maxIndex = i;
}
}
string bestRats[2];
bestRats[0] = r[maxIndex]; // store the best
ratMoves[maxIndex] = INT_MIN; // remove the best from array of rat moves
bestRats[1] = r[getMaxi(ratMoves, 5)]; // get the second best & store it
breed(bestRats);
}
void breed(string r[]) {
int cap = 10;
string c[5];
for (int j = 0; j<5; j++)
for (int i = 0; i<190; i++) {
int check = rand() % cap + 1;
if (check % 2 == 0) {
if (check == 0)
c[j] += rand() % 81 + 42;
else
c[j] += r[1][i];
}
else
c[j] += r[0][i];
}
best(c);
}
int main() {
string c[5];
for (int j = 0; j<5; j++)
for (int i = 0; i<190; i++)
c[j] += rand() % 81 + 42;
best(c);
}
Declare
void breed(string r[]);
on the top of file before first usage or include appropriate header file containing this declaration.
c++ checks for function names at the moment it reads them in the code (symbolically). if it hasn't read it yet, it doesn't know it exists. that's why you at least need to declare a function's prototype before using it in your code.
ergo, here you need to at least put
void breed(string r[]);
before using the function.
When the compiler processes your code, it starts at the top and goes to the end. At any given point in this process, it only "knows" about things it's already seen. So when you try to call the breed function from the best function, it doesn't know what you're talking about because it hasn't seen anything called breed yet.
To fix this, you need to let the compiler know what the breed function is before you attempt to use it. There are a few ways to do this. The easiest would be to move the entire breed function above the best function in your source file. An alternate would be to declare the breed function higher up in the file before defining it later. To declare it, simply include the line void breed (string r[]); somewhere (don't forget the ; at the end). This way the compiler knows that "breed" refers to a function that takes an array of strings and returns nothing, which is enough for it to compile calls to the function.
So I'm creating a lottery ticket with random values and then sorting it. I'm not worried about the sorting technique since the teacher isn't looking for classes etc. on this assignment and it works, however, my ticket values that I produce - despite using srand (time(0)) and then later the rand() % 40 + 1 - which I think should make my randoms between 1-40... but mainTicket[0] always equals 0. Any ideas? Sorry about the formatting, made me add extra spaces and mess up my indention.
#include <iostream>
#include <cstdlib>
#include <time.h>
using namespace std;
void mainLotto (int main[]);
void lottoSort (int ticketArr[]);
int main()
{
int mainTicket[5];
srand (time(0));
mainLotto(mainTicket);
do
{
lottoSort(mainTicket);
} while (mainTicket[0] > mainTicket[1] || mainTicket[1] > mainTicket[2] || mainTicket[2] > mainTicket[3] || mainTicket[3] > mainTicket[4] || mainTicket[4] > mainTicket[5]);
for (int i = 0; i < 5; i++)
{
cout << mainTicket[i] << "\n\n";
}
return 0;
}
///
/// <> Creates the actual lottery ticket
///
void mainLotto (int main[])
{
// Creating the ticket
for (int i = 0; i < 5; i++)
{
main[i] = rand() % 40 + 1;
}
}
///
/// <> Sorts the actual lottery ticket
///
void lottoSort (int ticketArr[])
{
// Sorting the ticket
for (int j = 0; j < 5; j++)
{
if (ticketArr[j] > ticketArr[j+1])
{
int temp;
temp = ticketArr[j+1];
ticketArr[j+1] = ticketArr[j];
ticketArr[j] = temp;
}
}
}
I see two problems with your arrays being accessed out of bounds:
Here:
int main()
{
int mainTicket[5];
srand(time(0));
mainLotto(mainTicket);
do
{
lottoSort(mainTicket);
}
while(mainTicket[0] > mainTicket[1] || mainTicket[1] > mainTicket[2]
|| mainTicket[2] > mainTicket[3] || mainTicket[3] > mainTicket[4]);
// || mainTicket[4] > mainTicket[5]); // OUT OF BOUNDS!!!
for(int i = 0; i < 5; i++)
{
cout << mainTicket[i] << "\n\n";
}
return 0;
}
And here:
void lottoSort(int ticketArr[])
{
// Sorting the ticket
for(int j = 0; j < 4; j++) // j < 4 NOT 5!!! <== WAS OUT OF BOUNDS
{
if(ticketArr[j] > ticketArr[j + 1])
{
int temp;
temp = ticketArr[j + 1];
ticketArr[j + 1] = ticketArr[j];
ticketArr[j] = temp;
}
}
}
Likely the sort routine was dragging in a zero from out side the array bounds.
I just printed the item you claim to be always zero, after the mainLotto() and it yielded 30.
I suspect the problem lies where you tell us not to look. :)
In the sorting function you do:
for (int j = 0; j < 5; j++) {
if (ticketArr[j] > ticketArr[j + 1]) {
The array is of size 5. Your j will take eventually a value equal to 4.
Then you do ticketArr[j + 1], which is actually an out of bound access.
The fix is to go until 4 in your loop, not 5.
As Galik said, mainTicket[4] > mainTicket[5] is also an out of bounds access and after reading my answer, you should be able to understand why. :)
This is a question from a ZCO (Zonal Computing Olympiad; Indian IOI qualifying contest) paper.
Basically, it revolves around finding the number of distinct pairs of elements from a set of numbers whose sum does not exceed a certain value.
My solution works on all except the last test case (on a certain private server, the test case itself is not available), on which it exceeds the 3-second time limit by half a second.
Am I missing something, algorithmically? A few pointers would be nice.
Here is my code:
#include <iostream>
#include <vector>
#include <queue>
#include <algorithm>
using namespace std;
int main() {
int n, k;
cin >> n >> k;
vector<int> hardness;
hardness.reserve(n);
int temp;
for(int i = 1; i <= n; ++i) {
cin >> temp;
if (temp < k) {
hardness.push_back(temp);
}
}
sort(hardness.begin(), hardness.end());
int mx = hardness.back(); //Max element
int chewableCombinations = 0, cur = 0;
for(int i = 0; i < hardness.size() - 1; ++i) {
cur = hardness[i];
if(cur == 0 || cur + mx < k) {
chewableCombinations += hardness.size() - i - 1;
continue;
}
for(int j = i + 1; j < hardness.size(); ++j) {
if(cur + hardness[j] < k) {
++chewableCombinations;
} else break; //we've crossed the limit
}
}
cout << chewableCombinations << endl;
}
If hardness[i]+hardness[j] < k then hardness[i]+hardness[m] < k for all m < j.
You don't have to check them all.
Okay, so I'm a complete noob. I'm trying my hand at Project Euler to get better at C++. I'm doing problem #1, but I'm not getting the correct output. When I run it, I get that numTotalThree is -3, and numTotalFive is -5, and that numTotal is 0. There's something wrong with my functions, but I'm not sure what I've done wrong. How do I fix this?
#include <iostream>
using namespace std;
int main()
{
int amount = 1000;
int numOfThree = amount / 3;
int numOfFive = amount / 5;
int numTotalThree = 0;
int numTotalFive = 0;
int numTotal = numTotalThree + numTotalFive;
cout << numOfThree << endl;
cout << numOfFive << endl;
for(int i = 0; i <= numOfThree; i++)
{
numTotalThree += numTotalThree + 3;
}
cout << numTotalThree << endl;
for(int i = 0; i <= numOfFive; i++)
{
numTotalFive += numTotalFive + 5;
}
cout << numTotalFive << endl;
cout << numTotal << endl;
system("PAUSE");
return 0;
}
I guess you need something like this:
int sum = 0;
for (int i =0; i < 1000; ++i){
if(i % 3 == 0 || i % 5 == 0){
sum += i;
}
}
Later edit: I don't know why you want to count the numbers divisible with 3 or 5 that are less than 1000. The problem (Project Euler - Problem 1) asks for the sum of all the numbers less than 1000, divisible with 3 or 5.
C++ is not a functional language it's procedural - that means you have to do things in order. When you do this:
int numTotalFive = 0;
int numTotal = numTotalThree + numTotalFive;
It will be executed then and there and not again when numTotalThree and numTotalFive are updated. If you don't touch it again that's the value that will be output.
Here's an idea to go on:
Check how many are divisible by three by checking that the remainder %==0. Do the same for five, and then for both of them. Subtract from the total of the first two the number that is divisible by both to get an accurate answer.
int divisibleByThree=0;
int divisibleByFive=0;
int divisibleByBoth=0;
int total;
for(int i=0; i<1000; i++)
{
if (i%3==0)
divisibleByThree++;
if (i%5==0)
divisibleByFive++;
if (i%5==0) && i%5==0)
divisibleByBoth++;
}
total = divisibleByThree + divisibleByFive - divisibleByBoth;
return total;
Your
numTotalThree is overflowing for n in [0, 333]
3/2*(-2 + 2n)
Similarly numTotalFive for n in [0, 200]
5/2*(-2 + 2n)
So you're seeing negative values.
As other suggested you probably need to revisit your logic.
All you need is just to sum up the numbers in [0,1000] that are divisible by 3 or 5
size_t total =0;
for (size_t x =0; x < 1000; x++){
if( (x % 3 == 0) || (x % 5 == 0) ){
total += x;
}
}