UVa 3n+1 Case Recursive Stack Overflow - c

im trying to solve this very first challange but i get stuck,
i like fast program, so i decided to use recursive method not iteration
unfortunately, when the input is a big integer (100000 > input > 1000000), its often crash
so i debug it, and it shows stack overflow error
please help me, i dont know what to do, ive tried to change data type to unsigned long, unsigned int, etc, but none of it works
here is my code,
im using ANSI C
#include "stdio.h"
int cek(int n) {
return n % 2;
}
int fung(int n,int c) {
if (n == 1) {
return c;
}
if (!cek(n)) {
return fung(n/2,++c);
}
else {
return fung((n*3)+1,++c);
}
}
int comp(int i,int j,int tmp) {
int temp;
if (i == j)
return tmp;
temp = fung(i,1);
if (temp > tmp)
return comp(++i,j,temp);
else
return comp(++i,j,tmp);
}
int main() {
int i,j,tmp;
while (scanf("%d %d",&i,&j)) {
if (i > j) {
tmp = i;
i = j;
j = tmp;
}
printf("%d %d %d\n",i,j,comp(i,j,0));
}
return 0;
}
PS: sorry for my stupidness, im really a newbie #_#

Recursion is not likely to be faster than iteration, and in fact it's likely to be slower.
The call stack has a limited size, and if your recursion goes deeper than that, there's nothing you can do about it. Especially in the Collatz problem, there's no way to tell up front how many steps you'll need. Rewrite this using an iterative method instead.
(If your compiler does tail call optimization, recursion might still work. But TCO is not required by the standard, so it will lead to unportable code. And apparently, your compiler does not optimize this particular tail call anyway.)

Not a C expert, but usually there is a call stack depth limit enforced by the compiler. Probably you can change this with a compiler flag, but this will not solve your problem. Making the algorithm iterative instead of recursive will fix it.
Recursive algorithms won't go faster than iterative ones, usually. But they are typically nicer to understand. (= more elegant)

Okay guys,
i found it!!!
so this is my code, i still use recursion but only for the inner loop fung(),
im not really impressed of it, because its need 0,5 sec to count input 1 and 1000000, someone's code outhere can do it in 0 sec, LOL
i change the outer loop comp() with iterative method,
look here
#include "stdio.h"
/*#include "windows.h"*/
int cek(int n) {
return n % 2;
}
unsigned int fung(unsigned int n,unsigned int c) {
if (n == 1) return c;
if (!cek(n)) return fung(n/2,++c);
else return fung((n*3)+1,++c);
}
/*
Above recursion will looked like this in iterative method
int func(int n) {
int c=1;
while (n != 1) {
c++;
if (n % 2 == 0)
n=n/2;
else
n=(n*3)+1;
}
return c;
}
*/
/*Outer Loop*/
int iter(int i,int j) {
int tmp1=0,tmp2;
while (i <= j) {
tmp2 = fung(i,1);
if (tmp1 < tmp2)
tmp1 = tmp2;
i++;
}
return tmp1;
}
int main() {
unsigned int i,j,s,f;
while (scanf("%d %d",&i,&j)) { /*UVa Standard, infinite loop*/
/*s = GetTickCount();*/
printf("%d %d %d",i,j,iter(i,j));
/*f = GetTickCount();
printf("%lu\n",f-s);*/
}
return 0;
}

Related

Why is my factorial program using recursion not working

I am new to coding. so I wanted to write a c program using recursion to calculate the factorial of a number.
#include <stdio.h>
int fact(int a) {
int n = 1;
if (a != 0)
return;
else
n = n * a;
a--;
fact(a);
return n;
}
int main() {
printf("%d", fact(5));
return 0;
}
This is the program I have written. I know this is probably wrong but I think I would understand programming better if I was able to understand why the above program is exactly wrong.
Because whenever you pass any value other than 0 to fact your code exits without even returning a value:
if(a!=0)
return;
You should get at least a warning from your compiler that this is invalid code, since fact is expected to always return an int value.
But even more so, this is a logical error.
Did you mean to write:
if (a == 0) return 1; //0! = 1
Lev M. pointed out your mistakes in his answer. This is a working recursive implementation of the factorial algorithm.
unsigned int fac(unsigned char n)
{
if (n == 0)
return 1;
return n * fac(n - 1);
}

How to Optimize this Code?Code for Fibonacci-Prime?

My Code
#include<stdio.h>
int isprime(long int n);
int isfib(long int n);
int main()
{
int t;
long int i;
scanf("%d",&t);
while(t--)
{
scanf("%ld",&i);
if(isprime(i))
{
printf("%d\n",isfib(i));
}
else
{
printf("0\n");
}
}
}
int isprime(long int n)
{
int j;
if(n==1)
{
return 0;
}
for(j=2;j<=n/2;j++)
{
if(n%j==0)
{
return 0;
}
}
return 1;
}
int isfib(long int n)
{
long int a=0,b=1,c=0;
while(1)
{
c=a+b;
if(c<n)
{
a=b;
b=c;
}
else if(c==n)
{
return 1;
}
else
{
return 0;
}
}
}
T is no. of test cases.
Input 3 2 4
Output 1 1 0
Code is correct. But I want to execute with O(n)complexity.
Could you please me to, how to optimize this code, I want to learn code optimization in only this c programming language.
ERROR Your program took more time than expected.
expected time>1.12Sec
For starters, you have a very slow implementation of isprime. This one is way faster:
int isprime(int n) {
if(n == 1) return 0;
int i=2;
while(i*i<n) {
if(n%i == 0)
return 0;
i++;
}
return 1;
}
I'm pretty sure you can find something similar online for the fibonacci sequence.
However, it seems like you will receive a pretty big amount of numbers. Then it's a waste checking the same number again. You can use the following idea to take advantage of that.
int isprimeandsaveresult(int n, char * arr) {
if(arr[n] == 1) return 1;
if(arr[n] == 0) return 0;
return arr[n] = isprime(n);
}
Here, arr is a huge array initialized to something else than 1 or 0. I chose char to save memory, but this can be improved further by some hash function. You can use the same principle for fibonacci numbers.
I am quite new to programming when compared to some veterans so correct me if I'm mistaken. I see no pointers in your code that means some of your variables could be converted into register storage class.
Register class variables are stored in CPU registers not in memory so for frequently used variables it is very nice for optimization. In your case "i" is strongly recommend but this can be implemented to all your variables.

Recursion with Max Integer

I am writing a program to calculate the factorial of a number. I am using recursion to solve this problem. The problem I am running into is that once I reach number 13, it will throw garbage numbers because of INT's limit. What I want to do is implement a way to catch the error when it happens (without hard cording that at x=13 it has to stop, but rather by the output). This is my attempt:
#include <stdio.h>
int factorial( int n)
{
printf("Processing factorial( %d )\n", n);
if (n <= 1)
{
printf("Reached base case, returning...\n");
return 1;
}
else
{
int counter = n * factorial(n-1); //Recursion to multiply the lesser numbers
printf("Receiving results of factorial( %d ) = %d * %d! = %d\n", n, n, (n-1), counter);
if( counter/n != factorial(n-2) ) //my attempt at catching the wrong output
{
printf("This factorial is too high for this program ");
return factorial(n-1);
}
return counter;
printf("Doing recursion by calling factorial (%d -1)\n", n);
}
}
int main()
{
factorial(15);
}
The problem with this is that the program now never terminates. It keeps on looping and throwing me random results.
Since I cannot answer my own question, I will edit with my solution:
int jFactorial(int n)
{
if (n <= 1)
{
return 1;
}
else
{
int counter = n *jFactorial(n-1);
return counter;
}
}
void check( int n)
{
int x = 1;
for(x = 1; x < n+1; x++)
{
int result = jFactorial(x);
int prev = jFactorial(x-1);
if (((result/x) != prev) || result == 0 )
{
printf("The number %d makes function overflow \n", x);
}
else
{
printf("Result for %d is %d \n", x, result);
}
}
}
A better way to do it:
if (n <= 1) {
return 1;
} else {
int prev_fact = factorial(n - 1);
if (INT_MAX / prev_fact < n) { /* prev_fact * n will overflow */
printf("Result too big");
return prev_fact;
} else {
return prev_fact * n;
}
}
Uses a more accurate check (I hope) for whether the multiplication will overflow, and doesn't add any more calls to factorial.
Update
After looking more closely, turns out I missed the fact that gmp is also implemented for C. Here is the solution in C
I've been able to run it on my macbook pro, using homebrew to install gmp (brew isntall gmp)
#include <gmp.h>
#include <stdio.h>
void factorial(mpz_t ret, unsigned n) {
if (n <= 1) {
mpz_set_ui(ret, 1);//Set the value to 1
} else {
//multiply (n-1)! with n
mpz_t ret_intermediate;
mpz_init (ret_intermediate);//Initializes to zero
factorial(ret_intermediate, n-1);
mpz_mul_ui(ret, ret_intermediate, n);
}
return;
}
int main(){
mpz_t result;
mpz_init (result);
factorial(result, 100);
char * str_result = mpz_get_str(NULL, 10, result);
printf("%s\n", str_result);
return 0;
}
Original Answer
After quick googling, I found the following solution. Note this is a C++ solution. I briefly descirbe how you could do the same thing in ANSI C at the bottom.
Big numbers library in c++
https://gmplib.org/ This c++ library can work on numbers arbitrarily large.
Checkout https://gmplib.org/manual/C_002b_002b-Interface-General.html
The whole code could look something like....
#include <gmpxx.h>
#include <iostream>
mpz_class factorial(unsigned n) {
if (n <= 1) return mpz_class(1);
return mpz_class(n) * factorial(n-1);
}
int main(){
mpz_class result = factorial(100);
std::string str_result = result.get_str();
std::cout << str_result << std::endl;
return 0;
}
The ANSI C Version
You could implement the same thing using ansi C, with a structure to hold expanding list of numbers(using linked-list or any other expandable arraylist containers), and you'd only need to implement three methods... initialize, multiply and convert to string.

Why we can't use static variables to achieve tail recursion?

I am learning C, so I am writting some little exercises in C to practice the language.
I have experience with functional code, so I love recursion. I think that it would be great to achieve tail recursion using C static variables, so additional arguments or helper functions would not be required.
This code to calculate a factorial using recursion, fails:
long long int fact(int n)
{
static long long int result = -1;
if(n <= 0) {
if(result < 0)
return 1;
else {
long long int temp = result;
result = -1;
return temp;
}
} else {
result *= n;
fact(n - 1);
}
}
However, for some reason, I cannot do this in C. Is there an idiom to the same that? Is it just my compiler? What about memoization?
Thanks a lot.
Your code is broken since it has a control path where it doesn't return a value. This works fine:
long long int fact(int n)
{
static long long int result = 1;
if(n <= 1) {
long long int temp = result;
result = 1;
return temp;
} else {
result *= n;
return fact(n - 1);
}
}
GCC does successfully transform the tail recursion to iteration.
In general, I think the reason to avoid using statics for tail recursion is simply because the function loses reentrancy. So much code ends up having to run in a multithreaded environment these days that it's hard to justify leaving function-local static "landmines" in code. I do admit this is as much opinion as technical argument. The non-static tail recursive code:
static inline long long int fact_(int n, long long int result)
{
if(n <= 1) {
return result;
} else {
return fact_(n - 1, result * n);
}
}
long long int fact(int n)
{
return fact_(n, 1);
}
is if anything a bit easier to write - notably both versions are exactly 13 LOC - and compiles just as efficiently to iteration but without needing static data.
You don't seem to have an explicit return value from your else block. Are you not getting compiler warnings on that? Please make sure you're compiling with all warnings turned on.
Basically, you need to add return result; to the end of your else block otherwise how are you going to return the result back to the original caller? Remember, return only pops one function call, and you're an arbitrary depth when you call return because of all the recursive calls to fact() you've made in your else block.
int factorial(int n)
{
static int m = 1;
m *= n;
if (n > 1)
factorial(n - 1);
return m;
}

Why does my recursive function seg fault in C?

My program is as follows:
#include <stdio.h>
int collatz(int seed, int count) {
int next = 0;
if (seed % 2 == 0) {
next = seed / 2;
} else {
next = 3 * seed + 1;
}
count++;
if (next == 1) {
return count;
} else {
return collatz(next, count);
}
}
int main() {
int max = 0;
int index = 0;
int i;
for (i=1; i<1000000; i++) {
int current = collatz(i, 1);
if (current > max) {
max = current;
index = i;
}
}
printf("%i\n", index);
return 0;
}
I understand that recursion normally only goes to a certain depth. However as far as I can tell I have implemented tail recursion which should stop the seg fault. If I set i to 100,000 the program runs which leads me to believe the underlying algorithm is correct. However at one million I get:
Segmentation fault: 11
What am I doing wrong?
If you use a debugger you may find that indeed your function is not tail-recursive. But why not? Probably because you simply forgot to enable optimization during compilation. On my system (GCC on Mac OS), a default build will crash, but building with the -O3 option will let it run (at least for a lot longer than otherwise; I didn't want to kill my battery testing).
If you are running it with 1 million i would say you are probably just running out of stack space causing a segfault
What compiler/os are you using in VS stacksize is 1MB by default but it can be increased.
I am not sure about other compiler/os combinations
collatz function is causing the overflow in the middle of a calculation. (it's stack overflow for that).
note:compiler optimization for tail recursion may or may not be done.
use long long (Int64).
int collatz(long long seed, int count) {
long long next = 0;
if (seed % 2 == 0) {
next = seed / 2;
} else {
next = 3 * seed + 1;
}
count++;
if (next == 1) {
return count;
} else {
return collatz(next, count);
}
}

Resources