Project Euler #14: What's wrong with this code?
An answer to this question on Stack Overflow.
Question
This is related to the "Project Euler Problem 14"
As I think, my logic and the code is good enough,but it may take few seconds to give the answer. But when i run this code, the program stops when "starting_number" is around 103152(i can't remember the number exactly).
Can anybody please have a look at this code and, tell me where and what's wrong with this code.
Here's the code :
#include<stdio.h>
int starting_number;
int number_of_terms;
int j=0,k=0;
int term;
int main(){
for(starting_number=2;starting_number<1000000;starting_number++){
term = starting_number;
number_of_terms = 1;
while(1){
{
if(term%2==0){
term = term/2;
number_of_terms++;
} else if(term%2!=0){
term = 3*term + 1;
number_of_terms++;
}
}
if(term == 1) break;
}
if(j>=number_of_terms) //finding which chain is longer
j=j;
else if(j< number_of_terms) {
j= number_of_terms;
k=starting_number;
}
printf("\n%d",starting_number);
}
printf("\n%d(%d)\n",k,j);
return 0;
}
Answer
This one's mildly tricky, but your problem is here:
if(term == 1) break;
If the variable term becomes very large (as it can easily do) then it can overflow the int datatype.
When this happens term becomes negative. The C language modulus of a negative odd number is itself negative. Therefore, the end condition for your loop is never met.
Solve this problem by using a larger data type such as unsigned long long.
A less convoluted version of your code would appear as follows. Note that I have eliminated the global variables (those outside of your main function) because global variables are evil. I've replaced your infinite while-loop with a loop that uses an end condition. I've reduced duplication of code within the while-loop. I've eliminated the j=j case. Since printf is a slow function to run, I've commented out the prinft you had in the for loop, which improves the run-time significantly.
#include <stdio.h>
int main(){
int number_of_terms;
unsigned long long term;
int j=0,k=0;
for(int starting_number=2;starting_number<1000000;++starting_number){
term = starting_number;
number_of_terms = 1;
while(term!=1){
if(term%2==0)
term /= 2;
else
term = 3*term + 1;
number_of_terms++;
}
if(j<number_of_terms){ //finding which chain is longer
j = number_of_terms;
k = starting_number;
}
//printf("\n%d",starting_number);
}
printf("\n%d(%d)\n",k,j);
return 0;
}
And, indeed, using unsigned long long solves the problem.