Understanding purpose of and difference between given recursive functions - c

Below are the two pieces of code. I could not understand how the pre-decrement operator in the first code functions. And I also could not understand how both of the codes differ in their functionality.
Code 1:
int foo (int val) {
int x = 0;
while (val > 0) {
x = x + foo(--val);
}
return val;
}
Code 2:
int bar (int val) {
int x = 0;
while (val > 0) {
x = x + bar(val - 1);
}
return val;
}

Consider the original code:
int foo(int val) {
int x = 0;
while (val > 0) {
x = x + foo(val--); // Post-decrement
}
return val;
}
When foo() calls itself recursively, the value passed to the recursive call is the same as the value passed to the current call, so the program will eventually exceed the stack limit and crash. It won't terminate normally.
Now consider the revised code:
int foo(int val) {
int x = 0;
while (val > 0) {
x = x + foo(--val); // Pre-decrement
}
return val;
}
Now the recursion is finite; if val is positive, then the recursive call is made with a smaller value, so the recursion stops. If val is negative, there is no recursion, of course.
However, since the code returns val, it will always return either 0 (for a non-negative input, because the loop counts down until val == 0) or what was provided (for a negative input; the loop body is never executed). The recursion keeps adding 0 to x, so x remains 0 too (but it's a 'set but unread' variable so it could be eliminated, and writing x += foo(val--); would be more idiomatic C). It would be accurate to say the revised code is equivalent to:
int foo(int val) { return (val < 0) ? val : 0; }
Even returning x doesn't fix all the problems. It returns 0 for non-negative inputs and 0 for negative inputs (but it doesn't crash):
int foo(int val) {
int x = 0;
while (val > 0) {
x += foo(--val); // Pre-decrement
}
return x;
}

Related

Difference in the C codes?

Code 1 :-
int f(int val) {
int x=0;
while(val > 0) {
x = x + f(val--);
}
return val;
}
Code 2:-
int g(int val) {
int x = 0;
while(val > 0) {
x= x + g(val-1);
}
return val;
}
What is the difference in the execution of the codes f(3) and g(3) ?
The Code 1 is quite clear to me. Then f(3) will keep calling itself, getting deeper and deeper, and when the space used to keep track of recursive function, it is filled up, and we get the stack overflow error.
But, I am actually stuck in the execution of the 2nd code. I ran it and got infinite loop.
Also, I have read that val-- can be written as val-1. So, How am I going wrong in interpreting the line val-1, as both of them are behaving quite different .
val-- is equivalent to val = val -1 so it decreases the value of val by 1 and stores the new value as well (decrementing). While val -1 just decreases and returns the new value without storing it in the variable val (no actual decrementing hapenning). This is why you have an infinite loop. I recommend these changes:
int g(int val) {
int x = 0;
while(val > 0) {
val = val - 1;
x= x + g(val);
}
return val;
}
Here is a reference on decrement and increment operators: http://en.cppreference.com/w/cpp/language/operator_incdec
val-- decreases val by 1 and saves it back into val, while val - 1 simply subtracts 1 from val which means you will never escape your while loop.

Search of an element on a unsorted array recursively

This is an exercise that I took from an exam. It asks to write a function that receives an unsorted array v[] and a number X and the function will return 1 if X is present in v[] or 0 if X is not present in v[]. The function must be recursive and must work in this manner:
1. Compares X with the element in the middle of v[];
2. The function calls itself (recursion!!) on upper half and on the lower half of v[];
So I've written this function:
int occ(int *p,int dim,int X){
int pivot,a,b;
pivot=(dim)/2;
if(dim==0) //end of array
return 0;
if(*(p+pivot)==X) //verify if the element in the middle is X
return 1;
a=occ(p,pivot,X); //call on lower half
b=occ(p+pivot,dim-pivot,X); //call on upper half
if(a+b>=1) //if X is found return 1 else 0
return 1;
else{
return 0;
}
}
I tried to simulated it on a sheet of paper and it seems to be correct (Even though I'm not sure) then I've written it on ideone and it can't run the program!
Here is the link: https://ideone.com/ZwwpAW
Is my code actually wrong (probably!) or is it a problem related to ideone. Can someone help me? Thank you in advance!!!
The problem is with b=occ(p+pivot,dim-pivot,X); when pivot is 0. i.e. when dim is 1.
the next function call becomes occ(p,1,X); This again leads to the call occ(p,1,X); in a continuous loop.
It can be fixed by adding a condition to the call, as shown in the code below.
int occ(int *p,int dim,int X){
int pivot,a=0,b=0;
pivot=(dim)/2;
if(dim==0){
return 0;
}
if(*(p+pivot)==X)
return 1;
if (pivot != 0)
{
a=occ(p,pivot,X);
b=occ(p+pivot,dim-pivot,X);
}
if(a+b>=1)
return 1;
else{
return 0;
}
}
The implemetation is causing a stack overflow, as the recursion does not terminate if the input contains only one element. This can be fixed as follows.
int occ(int *p, int dim, int X)
{
int pivot, a, b;
pivot = (dim) / 2;
if (dim == 0)
{
return 0;
}
if (*(p + pivot) == X)
{
return 1;
}
if (dim == 1)
{
if (*(p + pivot) == X)
{
return 1;
}
else
{
return 0;
}
}
a = occ(p, pivot, X);
b = occ(p + pivot, dim - pivot, X);
if (a + b >= 1)
{
return 1;
}
else
{
return 0;
}
}
It's enought to change only this one line in the source code to avoid the endless loop with occ(p,1,X):
//if(dim==0) //end of array
if (pivot == 0)
return 0;

Recursive Fibonacci in C

I'm trying to figure out why this code isn't working.
#include <stdio.h>
int main()
{
int num;
puts("what index of the Fibbonaci series do you want?");
scanf("%d", &num);
num = fib(num);
printf("%d", num);
return 0;
}
int fib(int num)
{
if (num == 0)
return 1;
else if (num == 1)
return 1;
else return (fib(num - 1)+fib(num-2));
}
P.S. I'm trying to keep it as simple as possible, and I was told that index's 0 and 1 are equal to 1.
Firstly, your function is not declared before main() and that is why your program does not run1.
Secondly, Fibonacci Sequence is defined as either:
1, 1, 2, 3, 5, 8,...
or
0, 1, 1, 2, 3, 5, 8,...
where the recursive relation describing it is : Fibn = Fibn-1 + Fibn-2
Which converted in C code would look like either something similar with what you got (first definition above), or a bit modified (using the second equally right definition):
int fib(int num)
{
if (num == 0) {
return 0;
} else if (num == 1) {
return 1;
} else {
return fib(num - 1) + fib(num - 2);
}
}
Note:
Both mine and your versions of the function are not very effective as they will make a lot of calls, most of them to calculate overlapping values, i.e. they will calculate a lot of overlapping subproblems. This could be fixed by using memoization.
Here is an example of an implementation, using the above notion of memoization:
// header needed for the container: map
#include <map>
int mem_fact (int i, std::map<int, int>& m) {
// if value with key == i does not exist in m: calculate it
if (m.find(i) == m.end()) {
// the recursive calls are made only if the value doesn't already exist
m[i] = mem_fact (i - 1, m) + mem_fact (i - 2, m);
}
// if value with key == i exists, return the corresponding value
return m[i];
}
int fast_factorial (int i) {
// key (Fibonacci index) - value (Fibbonaci number)
std::map<int, int> memo;
// initialize the first two Fibonacci numbers
memo.insert(std::pair<int,int>(0, 0));
memo.insert(std::pair<int,int>(1, 1));
return mem_fact(i, memo);
}
then in main,if you call both like so:
int slow_fib = fib(10);
int fast_fib = fast_factorial(10);
you will get the same result: slow_fib = fast_fib = 55, however fib() will have to make 177 calls and fast_factorial() only 19 calls.
1. error: 'fib' was not declared in this scope
fib(0) is 0, not 1. Whoever indicated/ordered that fib(0) is 1 is wrong.
Change
if (num == 0)
return 1;
to
if (num == 0)
return 0;
Best thing is to avoid recursive form as possible.
int fib(int index) -- first fibonacci number is at index 0
{
int a = 0;
int b = 1;
int c = 0;
for (int i = 0; i<index; ++i)
{
a = b;
b += c;
c = a;
}
return a; // <<-- value at index
}

number of zeros runtime error

This is a function i made to count number of zeroes at the end of the factorial of a number b recursively.
However i'm getting runtime error due to the used code.Pardon my naivety but any help in this would be appreciated.
int noz(int b)
{
int c=0;
int e = b;
if(e < 5)
return 0;
while(e > 0)
c = c + (e/5) + noz(e/5);
return c;
}
You are encountering "runtime error" because:
int c;
...
while(e > 0)
c = c + (e/5) + noz(e/5); // <-- HERE
you are using uninitialized local variable c, which produces undefined behavior.
You could zero-initialize this variable to prevent it happen:
int c = 0;
And also note that in case that argument of your function is greater or equal than 5, this function doesn't return anything (thanks to #Paul R for pointing this out) and another problem is that you have loop with the condition e > 0 but the loop doesn't change the value of e making it infinite loop.
Your function could look like this instead (I'm not sure what exactly is the desired logic here):
int noz(int b)
{
int c = 0;
if (b < 5)
return 0;
else
return c + (b/5) + noz(b/5);
}
//count n! tail zero
int noz(int n){
int count;
if(n < 5) return 0;
count = n / 5;
return count + noz(count);
}

UVA's 3n+1 wrong answer although the test cases are correct . . .?

UVA problem 100 - The 3n + 1 problem
I have tried all the test cases and no problems are found.
The test cases I checked:
1 10 20
100 200 125
201 210 89
900 1000 174
1000 900 174
999999 999990 259
But why I get wrong answer all the time?
here is my code:
#include "stdio.h"
unsigned long int cycle = 0, final = 0;
unsigned long int calculate(unsigned long int n)
{
if (n == 1)
{
return cycle + 1;
}
else
{
if (n % 2 == 0)
{
n = n / 2;
cycle = cycle + 1;
calculate(n);
}
else
{
n = 3 * n;
n = n + 1;
cycle = cycle+1;
calculate(n);
}
}
}
int main()
{
unsigned long int i = 0, j = 0, loop = 0;
while(scanf("%ld %ld", &i, &j) != EOF)
{
if (i > j)
{
unsigned long int t = i;
i = j;
j = t;
}
for (loop = i; loop <= j; loop++)
{
cycle = 0;
cycle = calculate(loop);
if(cycle > final)
{
final = cycle;
}
}
printf("%ld %ld %ld\n", i, j, final);
final = 0;
}
return 0;
}
The clue is that you receive i, j but it does not say that i < j for all the cases, check for that condition in your code and remember to always print in order:
<i>[space]<j>[space]<count>
If the input is "out of order" you swap the numbers even in the output, when it is clearly stated you should keep the input order.
Don't see how you're test cases actually ever worked; your recursive cases never return anything.
Here's a one liner just for reference
int three_n_plus_1(int n)
{
return n == 1 ? 1 : three_n_plus_1((n % 2 == 0) ? (n/2) : (3*n+1))+1;
}
Not quite sure how your code would work as you toast "cycle" right after calculating it because 'calculate' doesn't have explicit return values for many of its cases ( you should of had compiler warnings to that effect). if you didn't do cycle= of the cycle=calculate( then it might work?
and tying it all together :-
int three_n_plus_1(int n)
{
return n == 1 ? 1 : three_n_plus_1((n % 2 == 0) ? (n/2) : (3*n+1))+1;
}
int max_int(int a, int b) { return (a > b) ? a : b; }
int min_int(int a, int b) { return (a < b) ? a : b; }
int main(int argc, char* argv[])
{
int i,j;
while(scanf("%d %d",&i, &j) == 2)
{
int value, largest_cycle = 0, last = max_int(i,j);
for(value = min_int(i,j); value <= last; value++) largest_cycle = max_int(largest_cycle, three_n_plus_1(value));
printf("%d %d %d\r\n",i, j, largest_cycle);
}
}
Part 1
This is the hailstone sequence, right? You're trying to determine the length of the hailstone sequence starting from a given N. You know, you really should take out that ugly global variable. It's trivial to calculate it recursively:
long int hailstone_sequence_length(long int n)
{
if (n == 1) {
return 1;
} else if (n % 2 == 0) {
return hailstone_sequence_length(n / 2) + 1;
} else {
return hailstone_sequence_length(3*n + 1) + 1;
}
}
Notice how the cycle variable is gone. It is unnecessary, because each call just has to add 1 to the value computed by the recursive call. The recursion bottoms out at 1, and so we count that as 1. All other recursive steps add 1 to that, and so at the end we are left with the sequence length.
Careful: this approach requires a stack depth proportional to the input n.
I dropped the use of unsigned because it's an inappropriate type for doing most math. When you subtract 1 from (unsigned long) 0, you get a large positive number that is one less than a power of two. This is not a sane behavior in most situations (but exactly the right one in a few).
Now let's discuss where you went wrong. Your original code attempts to measure the hailstone sequence length by modifying a global counter called cycle. However, the main function expects calculate to return a value: you have cycle = calculate(...).
The problem is that two of your cases do not return anything! It is undefined behavior to extract a return value from a function that didn't return anything.
The (n == 1) case does return something but it also has a bug: it fails to increment cycle; it just returns cycle + 1, leaving cycle with the original value.
Part 2
Looking at the main. Let's reformat it a little bit.
int main()
{
unsigned long int i=0,j=0,loop=0;
Change these to long. By the way %ld in scanf expects long anyway, not unsigned long.
while (scanf("%ld %ld",&i,&j) != EOF)
Be careful with scanf: it has more return values than just EOF. Scanf will return EOF if it is not able to make a conversion. If it is able to scan one number, but not the second one, it will return 1. Basically a better test here is != 2. If scanf does not return two, something went wrong with the input.
{
if(i > j)
{
unsigned long int t=i;i=j;j=t;
}
for(loop=i;loop<=j;loop++)
{
cycle=0;
cycle=calculate(loop );
if(cycle>final)
{
final=cycle;
}
}
calculate is called hailstone_sequence_length now, and so this block can just have a local variable: { long len = hailstone_sequence_length(loop); if (len > final) final = len; }
Maybe final should be called max_length?
printf("%ld %ld %ld\n",i,j,final);
final=0;
final should be a local variable in this loop since it is separately used for each test case. Then you don't have to remember to set it to 0.
}
return 0;
}

Resources