I am trying to understand how to use recursion in C, and I can't get how return works in it.
Please consider the following code:
int recur(int i)
{
printf("recur: i = %d\n", i);
if (i < 3)
{
recur(i + 1);
return 10;
}
else if (i < 5)
recur(i + 1);
return i;
}
int main(void)
{
int i = 0;
i = recur(i);
printf("i = %d\n", i);
return 0;
}
The output is:
recur: i = 0
recur: i = 1
recur: i = 2
recur: i = 3
recur: i = 4
recur: i = 5
i = 10
What does the last return, return i, do? Does this code even make sense?
The recursive calls of the function do not influence on the returned value. Only the first return met in the first instance of your recursive function will return a value to the parent function. Any other return met will just stop the function's instance the program is currently in.
Thus as the function was called in main with the argument 0
int i = 0;
i = recur(i);
The first return met is located inside of an if statement:
if (i < 3)
{
recur(i + 1);
return 10;
}
In this case, the recur function is called before returning a value to main. It will create another instance of recur which will do some stuff, but after this instance of recur has ended, the main instance of recur will continue and, in this case, will return 10 to the function main.
To know what your recursive function will return to the main function, you can simply comment all calls to a new instance of the function:
int recur(int i)
{
if (i < 3)
{
//recur(i + 1);
return 10;
}
else if (i < 5)
{
//recur(i + 1);
}
return i;
}
In this case, this is what the program will read:
int recur(int i)
{
if (i < 3)
return 10;
return i;
}
I think this is one of the easiest recursive function to understand.
int pow(int n, int x)
{
if (n != 1)
return x * pow(n - 1, x)
else
return x;
}
Let's study pow(3, 2) : 2^3 = 2 * 2 * 2 = 8
First iteration : pow(3, 2) returns 2 * pow(2, 2)
Second iteration : pow(2, 2) returns 2 * 2* pow(1, 2)
Third iteration : n == 1 so pow(1, 2) returns x = 2 * 2 * 2 = 8
A recursive function returns a call to itself at the i + 1 step of the process. In order to avoid an infinite loop, you have to make sur you have a break condition, which leads to a return to something different from a self-call.
You got at least one answer which helpfully explains the behaviour of your code.
I want to provide help via a different, additional path here. Both together provide different view points for you.
For that purpose I provide a version of your code augmented by instrumentation, which tells you more verbosely what happens.
This allows you to play with the code and observe, that will give you the really helpful answer.
Note:
the for(c lines are only for suggestive indentation;
I chose not to use a function for this, feeling that it keeps the interesting function calls more prominent
I added a parameter "nesting", it is for
making a part of the (hopefully useful) output
show that usually the recursive nesting has some influence
I introduced a local variable "j",
to show what happens with the reutrn values in most cases
Code:
#include <stdio.h>
int recur(int i, int nesting)
{ int c;
for(c=0;c<nesting;c++) { printf(" ");}
printf("recur[%d](%i)", nesting, i);
if (i < 3)
{ printf("i <3, calling recur[%d](%d)\n", nesting+1, i+1);
recur(i + 1, nesting+1);
for(c=0;c<nesting;c++) { printf(" ");}
printf("returning 10 from recur[%d], with i==%d\n", nesting, i);
return 10;
}
else if (i < 5)
{
int j=0;
printf("i <5, calling recur[%d](%d)\n", nesting+1, i +1);
j=recur(i + 1, nesting+1);
for(c=0;c<nesting;c++) { printf(" ");}
printf("ignored return value from recur[%d](%d) is %d", nesting+1, i+1, j);
}
printf("\n");
for(c=0;c<nesting;c++) { printf(" ");}
printf("returning i from recur[%d], with i==%d\n", nesting, i);
return i;
}
int main(void)
{
int i = 0;
i = recur(i, 0);
printf("the last return value did not get ignored: i = %d\n", i);
return 0;
}
Output:
recur[0](0)i <3, calling recur[1](1)
recur[1](1)i <3, calling recur[2](2)
recur[2](2)i <3, calling recur[3](3)
recur[3](3)i <5, calling recur[4](4)
recur[4](4)i <5, calling recur[5](5)
recur[5](5)
returning i from recur[5], with i==5
ignored return value from recur[5](5) is 5
returning i from recur[4], with i==4
ignored return value from recur[4](4) is 4
returning i from recur[3], with i==3
returning 10 from recur[2], with i==2
returning 10 from recur[1], with i==1
returning 10 from recur[0], with i==0
the last return value did not get ignored: i = 10
Note:
The recur[n](m) is of course no C syntax.
It just indicates a call to the function "recur" on nesting level "n" with parameter "m".
(Especially do not confuse the "[]" with arrays, they are not present.)
return 0 is the return from the main function, not from your recursive code.
Related
int rec(int k)
{
static int temp = 0, counter = 0;
if(!k) return counter;
if(k%2 == 0){
counter++;
temp = rec(k/2);
}
if(k%2){
counter++;
temp = rec(k-1);
}
}
This function is supposed to get a number k and check how many operations are needed to get k to 0 only by multiplying by 2 or by adding 1.
this function works fine but returns zero instead of the last value in the counter. I tried to debug it, and I saw the counter value increasing, but after getting to the value it is supposed to return, the function goes back to complete all the calls, and returns 0.
I fixed it by making counter global and returning nothing, but my questions are:
Is there a way to fix it as it is with the counter inside the function?
Why is this function returning zero at the end?
Here's a nice recursive function that doesn't declare any variables at all, it's purely recursive!
int get_steps_to_zero(int n)
{
// Deal with negative values
if (n < 0) n *= -1;
if (n == 0) {
// Base case: we have reached zero
return 0;
} else if (n % 2 == 0) {
// Recursive case 1: we can divide by 2
return 1 + get_steps_to_zero(n / 2);
} else {
// Recursive case 2: we can subtract by 1
return 1 + get_steps_to_zero(n - 1);
}
}
get_steps_to_zero(457);
> 13
Others have addressed the general recursion issue, yet there remains a ...
Corner case
"this function works fine" --> Not quite.
The algorithm is an infinite loop for rec(-1) as it attempts -1 --> -2 --> -1 --> -2 ...
A better approach would sometimes add 1.
if(k%2) {
counter++;
// temp = rec(k-1);
temp = rec(k + (k < 0 ? 1 : -1));
}
This also well handles non-2's complement issue.
I will try to show a new side to this discussion,
Recursion is like a chain,
This means that any function can receive a value from its child and return a value to its parent.
In your program you are trying to return a value from the last child to the first parent,
So your program must have all links in the chain receive and send value in order.
But in your code you return a value only in the last call, and all other calls do not return this value back.
Your stop condition is here:
if(!k) return counter;
Only the last call enters this scope, but other calls do not reach any return statement.
they get to here:
if(k%2 == 0){
counter++;
temp = rec(k/2);
}
if(k%2){
counter++;
temp = rec(k-1);
here there is no return statement.
your compiler will warning you like this:
"warning: control reaches end of non-void function".
but your program will compile so it return zero like all non-void functions without return.
So if you want this program to work make it like Randomblock1, or like this:
int rec(int k)
{
static int counter = 0;
if(!k){
return counter;
}
else if(k%2 == 0){
counter ++;
counter += rec(k/2);
}
else{
counter++;
counter += rec(k-1);
}
return counter;
}
But this program also do not work well, what is the reason?
The reason is because you used by static variable.
It's a little hard to explain, but you can't use this recursion with a static variable, so add a patch to this line:
static int counter = 0;
like this
int counter = 0;
I hope what I wrote will be understandable
I am having trouble coming up with a working helper function for my main, I believe the problem with my main program not working is because of this helper function.
its is supposed to loop through an array and see if there is an empty frame, i.e. an element that equals 1.
i have an array like this
int freeFrames[8] = {0, 1, 1, 1, 1, 1, 1 , 1};
and the helper function like this
int findEmptyFrame(int freeFrames[])
{
int i, index;
for(i = 1; i < 8; i++)
{
printf("FreeFrame = %d\n",i); // simple print statment
if(freeFrames[i] == 1){
index = i;
return index;
}
else{
return -1;
}
}
}
when I loop thru the array in my main Program it only ever reaches the 1st frame and returns it and doesn't ever cycle thru the next next element besides the first one
this is the section in my main where i am calling the function
else{
x = findEmptyFrame(freeFrames);
printf("X IS %d\n",x );
if(x > 0){
printf("IN IF BEFORE findEmptyFrame\n");
PT[pageNumber].fNum = x;
PT[pageNumber].vi = 0;
frameNumber = PT[pageNumber].fNum;
PA = (frameNumber << d) + dNum;
fwrite(&PA,sizeof(unsigned long), 1, myWriteFile);
printf("The Logical Address is at %lx and Translated Physical Addres is at %lx\n",LA, PA);
lruCount[frameNumber] = clock;
reverseMap[x] = pageNumber;
}
and an example of what i am currently getting is something like this
IN IF BEFORE findEmptyFrame
The Logical Address is at b70 and Translated Physical Addres is at f0
FreeFrame = 1
X IS 1
The reason this is happening is because in your for loop, if the freeFrame[i] is not equal to 1, the if condition fails. It therefore goes to the else part and returns -1. Therefore, you cannot return -1 within the for loop. You have to return it outside, like below:
int findEmptyFrame(int freeFrames[])
{
int i, index;
for(i = 0; i < 8; i++)
{
printf("FreeFrame = %d\n",i); // simple print statment
if(freeFrames[i] == 1){
freeFrames[i] = 0; //Change here
return i;
}
}
return -1;
}
What this does is, if there is a 1 in the array, it returns the index. If not, the whole for loop ends and only then it returns -1.
Also, indexing in the for loop must start from 0.
If you want the first free frame to be marked used, you additionally have to do that before returning the index. Check the change in code.
int die[5] = { 0 };
int roll_die(void)
{
return rand(1, 6) % 6 + 1;
}
for (index = 0; index < 5; (++index) && (i++))
{
roll_die(die, 5); //tried as &die as well, but same problem
printf("die[%d]: %d\n\n", i, die[index]);
}
prints die[1] - die[5] will 0 values instead of randomly generated integers between 1 and 6
#include <stdio.h>
int roll_die()
{
return rand() % 6 + 1;
}
int main() {
int die[5] = { 0 }, index;
for (index = 0; index < 5; (++index))
{
die[index] = roll_die();
printf("die[%d]: %d\n\n",index, die[index]);
}
return 0;
}
you used rand wrong, didnt used the returned value, and the way you called the function was wrong.
hope that helps.
p.s.
its better also to call
srand(time(NULL));
once in the start
Rollling a Dice with JShell (Java)
https://www.youtube.com/watch?v=a2CIxn0C1qo
You are calling the function that takes no parameters (void) with parameters.
I'm talking about this line right here: roll_die(die, 5);
The way you declared and defined the function roll_die is so that it just returns a random number int roll_die(void)
Whatever value this function return must be assigned to someting like #t.elazari mentioned:
die[index] = roll_die();
Here you are saying that the value of the array die in the index index (die[index]) will equal whatever roll_die() returns.
Follow his example, I'm just giving you a short explanation of why you did it wrong.
The function that he mentioned (srand(time(NULL));) goes inside the main function, anywhere as long as it is BEFORE the for loop. This function changes the seed of the rand to be the current time. If you don't do this, your rand function will return the same values always, they are random but their seed is always the same.
Have you tried to replace roll_die(die, 5); by die[index] = roll_die(die, 5); ?
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
}
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;
}