Can anyone explain why does this recursive function crash? - c++

Why does this recursive (i'm not sure about it, the site i found this code said it was "recursive") code crash (i found this weird approach on Internet, but i'm honestly not understanding how it works) entering values >4000 (sometimes >4023, sometimes >4015, i really don't understand...)...
#include <iostream>
unsigned long long int sum(unsigned long long int k)
{
if (k > 0) {
return k + sum(k - 1);
}
else {
return 0;
}
}
int main()
{
unsigned long long int n;
std::cout << "This program prints the sum of the first N natural numbers.\n\
Enter N: _";
std::cin >> n;
std::cout << "The sum is: " << sum(n) << ".\n\
Press any key to exit...";
system("pause>nul");
return 0;
}
while this, instead, does not?
#include <iostream>
int main()
{
unsigned int n;
std::cout << "Questo programma stampa la somma dei primi N numeri naturali.\n\
Prego inserire N: _";
std::cin >> n;
unsigned long long int tmp = 0;
for (n; n != 0; --n) {
tmp += n;
//std::cout << tmp << ' ';
}
std::cout << "La somma \212: " << tmp << ".\n\
Premere un tasto per uscire...";
system("pause>nul");
return 0;
}

The recursive version uses a little bit of stack space every time it calls itself, so it is limited by the size of the stack and will crash if it calls itself too many times. It's a classic stack overflow error.
The iterative second version doesn't have that problem.

Your first approach
The first approach is recursive. That means that it calls the function sum() once for each k. Lets say, k is 2, than sum() is called twice and so on.
Each function call requires space on the stack for its parameters, local variables and some management data like the stack pointer, the return address to which the program jumps when the function returns and some other stuff. When you call sum() too often, lets say some 4000 times there is not enough space on the stack left for the very next call to sum(). In result you get a stack overflow and your application crashes.
The exact maximum of k you could provide until your app crashes depends on your system. That means, on a desktop with Windows, Linux or MacOS with a "big" stack you can call the function with k = round about 4000 times while on an embedded system the stack per thread may be lower, and your application crashes earlier.
Your second approach
Your second approach is not recursive and therefore does not require any additional space on the stack for calls to other functions. Therefore your application does not crash since you do not get the stack overflow from the first approach.
In addition, your second approach should run much faster since you do not require the time for the many function calls.

Related

warning: 'totalTemp' may be used uninitialized in this function and cout not printing to console

Trying to write a program displaying the average temperature in 24 hours, by the user typing in the temperature each hour. However, I'm just getting this error in code blocks:
warning: 'totalTemp' may be used uninitialized in this function [-Wmaybe-uninitialized]|.
and the console is just black when ran and not displaying anything.
#include <iostream>
using namespace std;
int main(void)
{
int i = 0;
while(i <= 24);
int newTemp;
int totalTemp;
{
cout << "Input temperature for the hour " << i << ":";
cin >> newTemp;
totalTemp = totalTemp + newTemp;
i++;
cout << "The average temperature for the day is " << totalTemp/24 << " degrees";
}
return (0);
}
How do I initialize it? and what is making my code not appear in the console when I'm trying to use cout?
How do I initialize it?
int totalTemp = 0;
and what is making my code not appear in the console when I'm trying to use cout?
while(i <= 24);
This is an infinite loop with an empty body. Infinite loops without observable side effects are undefined behavior. The compiler is allowed to produce the same output for your code as it would for int main() {}. You probably want while( i<=24) { .... Or rather use a for loop when the number of iterations is fixed.
Moreover, totalTemp/24 is using integer arithmetics. Maybe thats what you want, but more likely you want totalTemp/24.0. And also very likely you want to print the average outside of the loop instead of printing it in every iteration.

Google KickStart Round B Bus Routes Problem wrong answer?

I was practicing with google kickstart's round B bus route problem. I actually looked at their analysis and implemented their alternative answer.
I'll also paste the problem prompt below my code.
https://codingcompetitions.withgoogle.com/kickstart/round/000000000019ffc8/00000000002d83bf
And my solution passes the first test set but gets a wrong answer on the second test set. I have no idea what the second test set is, only that it's very big. I'm pretty confused as my solution follows the analysis of the problem, and is actually an implementation of the alternate provided solution to a T. I also have no idea how to figure out which test case could be giving a wrong answer, there seems to be so many possibilities!
I have no idea how to even debug such a vague answer. Maybe there are some edge cases I'm not considering?
#include <iostream> // includes cin to read from stdin and cout to write to stdout
#include <bits/stdc++.h>
using namespace std;
int main() {
int t, n, d;
cin >> t; // read t. cin knows that t is an int, so it reads it as such.
for (int i = 1; i <= t; ++i) {
cin >> n >> d; // read n and then m.
stack <int> bus;
for(int j=0; j<n; j++){
int x;
cin >> x;
bus.push(x);
}
while(!bus.empty()){
int b = bus.top();
bus.pop();
d = d - d%b;
}
cout << "Case #" << i << ": " << d << endl;
}
return 0;
}
****Here's a shortened version of the Problem Prompt ****
Problem
Bucket is planning to make a very long journey across the countryside by bus. Her journey consists of N bus routes, numbered from 1 to N in the order she must take them. The buses themselves are very fast, but do not run often. The i-th bus route only runs every Xi days.
More specifically, she can only take the i-th bus on day Xi, 2Xi, 3Xi and so on. Since the buses are very fast, she can take multiple buses on the same day.
Bucket must finish her journey by day D, but she would like to start the journey as late as possible. What is the latest day she could take the first bus, and still finish her journey by day D?
It is guaranteed that it is possible for Bucket to finish her journey by day D.
Input
The first line of the input gives the number of test cases, T. T test cases follow. Each test case begins with a line containing the two integers N and D. Then, another line follows containing N integers, the i-th one is Xi.
Output
For each test case, output one line containing Case #x: y, where x is the test case number (starting from 1) and y is the latest day she could take the first bus, and still finish her journey by day D.
Limits
Time limit: 10 seconds per test set.
Memory limit: 1GB.
my guess is using int is not sufficient as D can be up to 10^12 in test set 2
Edited: I verified my guess. You will be able to solve the problem by fixing this bug. And I believe the use of long long is common for coding contests, i.e. take note of the input/output constraints every time.
#include <iostream>
#include <bits/stdc++.h>
using namespace std;
int main ()
{
int t;
long long int x,i,j,n,d;
cin >> t;
for ( i = 0; i < t; i++)
{
cin >> n >> d;
stack < long long int >route;
for (j = 0; j < n; j++)
{
cin >> x;
route.push (x);
}
while (!route.empty ())
{
long long int c = route.top ();
route.pop ();
d = d - d % c;
}
cout << "Case #" << i+1 << ": " << d << endl;
}
return 0;
}

Simple program, cannot get for loop to execute

Brand new programmer, so green behind the ears that I could be a frog. The intent of this program is to use a for loop (not a simple formula) to add all integers up to a user designated value. It executes all code up to the for loop perfectly, however the for loop does not seem to run. Here is the code in question:
#include "stdafx.h"
#include <iostream>
int main(int num=0)
{
int sum = 0;
std::cout << "This program will sum all integers up to a given value";
std::cout << std::endl << std::endl;
std::cout << "Please enter a number "<<std::endl;
std::cin >> num;
std::cout << std::endl << "You've chosen the number " << num<<std::endl;
for (int i = 1; i <= num; ++i)
sum += i;
return (sum);
std::cout << "The sum of all numbers up to " << num << " is " << sum;
}
Any help is appreciated!
When it meets return for the first time, the program will be end.
Please put the return at the end of main function.
One more thing, shouldn't use parameter num in main function.
Write a separately function sum_all_integers and then call it in main function.
Good news: your code works! The issue is that when return (sum); is called, the function is exited, and the line that would print out your answer is not executed.
I would also recommend adding the using namespace std; line after your includes, so that you don't end up with so much std:: pollution. Also main should not take any arguments, so put that int num=0 line inside the main block.
Oh, you should also be aware of your return line indentation.
In this section
for (int i = 1; i <= num; ++i)
sum += i;
return (sum);
Your program will exit.
This boils down to what other answers have mentioned: return from main means exiting the program. Keep in mind that is is true even from within a loop like while or for - doing so is how one might design a search function which exits as soon as it has a result, for example.
To exit a for loop prematurely, use break. To continue to the next iteration and skip further code in the loop, use continue.
Also note that the indentation of return is misleading - it will be executed after the for loop, since the lack of brackets ({}) will make for only loop through the next line, which is sum += i; Keep in mind that C++ is not a whitespace sensitive language, so indentation means nothing to the logic (I like to abuse this in large blocks of similar code by tab-aligning). This is also a good example of why it is common practice to use brackets even when not strictly necessary. EDIT See also Apple's infamous "goto fail" bug.
You return the sum right after the loop:
for (int i = 1; i <= num; ++i)
sum += i;
return (sum);
This means, you sum up the numbers and then exit the program before you print the result.

(C++) Specific values in an array

I'm not sure how to title my question, but here goes. I am testing some features, and I have hit a snag.
What I want to know is how can I set up a "for" or "if" statement to only put values in an array that meet a criteria? For example, find every divisor for a number, but only put factors in an array.
Any help would be loved, source code can be provided if needed :). Yes, I am new, so be gentle!
#include <iostream>
using namespace std;
int main(){
int n;
int counter = 1;
cout << "What number would you like to use? ";
cin >> n;
int DiviArray[n];
for (int k=0,j=1;k<n;k++,j++)
{
DiviArray[k] = n-k;
}
int k = 3;
int factn[n];
cout << "Factors of " << n << ": " << endl;
for (int i=0, j=1;i<n;i++,j++)
{
factn[i] = n/DiviArray[i];
if(factn[i]*DiviArray[i]==n)
{
cout << counter << ". " << factn[i] << " x " << DiviArray[i] << endl;
counter++;
}
}
return 0;
}
EDIT: Decided to go with vectors, not sure if I can get it to work, but thanks for the feedback guys :)
Since you don't know in advance how many values will meet the condition, you should use a std::vector.
As a benefit, it keeps track of how many elements you've already added, so push_back will always use the next available index.
This also fixes
cin >> n;
int DiviArray[n];
which isn't legal C++.
If you only want to put the values into the array that match the condition, then you should only put a number into the array when the condition is matched. To do that, the statement that puts a number into the array has to be inside the if-block for the condition. I hope I don't need to explain why :)
This is the only time in your program where you actually do want two indices: one that is incremented every time through the loop (to count how many times to run the process), and one that is incremented only when you put a number in the array (to figure out where the next number goes). Everywhere else, you've created a completely useless j variable (the uselessness should be apparent from the fact that there is no code that actually uses the value, only code to set it).

Check for Identical Birthdays in a Specific group size in C++

I am brand new to this site. A friend told me about it and how much it has helped him, so here goes!
I am trying to create a program that will read in a certain size of a group. At this point it will then create random birthdays for each 'member' of the group (a day 1-365) and then compare to see if there were any identical birthdays in that set. The program will do this comparison for a given group size 10,000 times and keep track of how many of those trials yielded an identical birthday and return a percentage of the 10,000 trials in which there was a match.
The problem I am having is that the program will only ever return 100% and each successive run doubles that. So if a user decided to run again with a different group size, the answer then becomes '200%' then '300%' and so on.
Any help with this will be greatly appreciated!
//This program will ask for the number of people in a group and then output
//percentage likelyhood that two birthdays occur on the same day.
#include <iostream>
#include <cstdlib>
#include <ctime>
using namespace std;
int bdays [365];
const int loop = 10000;
int identicalBday;
void setZero (int []);
int totalDoubles (int [], int);
int main()
{
int grpSize = 1;
cout << "This program will ask for the number of people in a group and then output \npercentage likelyhood that two birthdays occur on the same day.";
cout << "\nHow many in group (0 quits)? ";
cin >> grpSize;
while (grpSize != 0)
{
int identicalBday = 0;
setZero (bdays);
cout << "In a group of " << grpSize << " the chances that two birthdays are the same is " << totalDoubles (bdays, grpSize) << "%." << endl;
cout << "\nHow many in group (0 quits)? ";
cin >> grpSize;
}
cout << "Thanks for using this program.";
cin.get();
cin.get();
return 0;
}
//Sets all indicies to 0
void setZero (int bdays [])
{
for (int i = 0; i < 365; i++)
bdays [i] = 0;
}
//Will add one to the array index associated with the random rumber
//If that index is already equal to 1, then it breaks (at least one other identical birthday exists)
//When it does break, will add one to the indenticalBday, allowing for division at the end
int totalDoubles (int bdays [], int grpSize)
{
int tmpRand;
for (int k = 0; k <= loop; k++)
{
for (int i = 0; i <= grpSize; i++)
{
srand((unsigned)time(0));
tmpRand = rand() % 365;
if (bdays[tmpRand] == 1)
{
identicalBday++;
break;
}
else
bdays [tmpRand]++;
}
}
return (identicalBday/loop)*100;
}
There are various errors with this code.
As Gabe mentioned it, the int identicalBday = 0 is local and doesn't reset the global one, which explain your 100% increase between runs. I think this error could be avoided by using a simple coding style rule: declare the variable where/when they are needed, that is the most locally possible and not at global level. For example, identicalBday and bdays should be declared inside totalDoubles(). Doing so will also remove all the side-effects of this function, and guarantee that everything is reset between calls.
By recalling srand() at each step, you reset the seed to the same value (time doesn't change fast enough) and kill all randomness. Only call it once.
You forget to recall setZero(bdays) after each grpSize loop.
(identicalBday/loop)*100; incorrectly do an integer division and round the result to 0 (or 1 if the srand error is not fixed). Use float division.
Fixing those seems to give correct result here (e.g. the classic 23 gives 53%)
Your problem is the line int identicalBday = 0; -- can you guess why?
Since you have int at the beginning, you are declaring a new variable that only exists within your while loop. That leaves the global identicalBday uninitialized, meaning that it never gets reset so it increases every time through the loop.