How to understand a recursive function call for large inputs - c

The result of the following code is 0,1,2,0, I totally understand after writing explicitly every call. But I wonder whether there is an easier method to understand what the recursive function want to realize and find the result faster? I mean we can't write all the call if a=1000.
#include<stdio.h>
void fun(int);
typedef int (*pf) (int, int);
int proc(pf, int, int);
int main()
{
int a=3;
fun(a);
return 0;
}
void fun(int n)
{
if(n > 0)
{
fun(--n);
printf("%d,", n);
fun(--n);
}
}

Your question isn't "what does this do?" but "how do I understand recursive functions for large values?".
Recursion is a great tool for certain kinds of problems. If, for some reason, you ever had to print that sequence of numbers, the above code would be a good way to solve the problem. Recursion is also used in contexts where you have a recursive structure (like a tree or a list) or are dealing with recursive input, like parsers.
You might see the code for a recursive function and think "what does this do?" but it's more likely that the opposite will happen: you will find a problem that you need to solve by writing a program. With experience you will learn to see which problems require a recursive solution, and that's a skill you must develop as a programmer.
The principle of recursion is that you perform a [usually simple] function repeatedly. So to understand a recursive function you usually need to understand only one step, and how to repeat it.
With the above code you don't necessarily need to answer "what output does this code give" but instead "how does it work, and what process does the code follow". You can do both on paper. By stepping through the algorithm you can usually gain insight into what it does. One factor that complicates this example is that it isn't tail-call recursive. This means you must do more work to understand the program.
To 'understand' any program you don't necessarily need to be able to simulate it and calculate the output, and the same applies here.

All you need to do is add some debug statements to understand it a little better. This is the result of the if statements I added to track through it:
start program
before if, n is = 3
before fun call, n is = 3
before if, n is = 2
before fun call, n is = 2
before if, n is = 1
before fun call, n is = 1
before if, n is = 0
printing = 0
before if, n is = -1
after second fun call, n is = -1
printing = 1
before if, n is = 0
after second fun call, n is = 0
printing = 2
before if, n is = 1
before fun call, n is = 1
before if, n is = 0
printing = 0
before if, n is = -1
after second fun call, n is = -1
after second fun call, n is = 1
end program

Related

Stacks and Recursion in C

#include <stdio.h>
void fun(int a) {
if (a > 0) {
fun(a / 10);
printf("%d", a % 10);
fun(a / 10);
}
}
int main() {
fun(12345);
return 0;
}
Here, as the function is calling itself at the start of the if block, shouldn't it print nothing, it will keep calling itself until the function argument becomes zero?
But instead, the output is 1213121412131215121312141213121
shouldn't it print nothing, it will keep calling itself until the
function argument becomes zero?
If I have understood correctly then you are right. The function will not output anything until a is equal to 0.
void fun(int a){
if(a > 0){
fun(a/10); // calls itself.
printf("%d",a % 10);
//...
Thus for this number 12345 the first output will be the most significant digit 1.
As the function calls itself twice
void fun(int a){
if(a > 0){
fun(a/10);
printf("%d",a % 10);
fun(a/10);
}
}
then for each digit of the number except the most significant digit the previous and next digits will be outputted twice on the left and on the right sides. For example
1 2 1
1 2 1 3 1 2 1
1 2 1 3 1 2 1 4 1 2 1 3 1 2 1
and so on.
I used embedded spaces for make the output more clear.
After the inner most function of the recursion has been finished (a>0) is evaluating to false it will execute the print statement and returns to the calling function.
The caller will print it's a%10 value and so on.
Not sure why you call fun(a/10) twice but this is why the output is printed twice.
Yuo do not need the second call
void fun(int a)
{
if(a)
{
fun(a/10);
printf("%d", a % 10);
}
}
https://godbolt.org/z/zWf64jjWe
Remember that it will not work for negative numbers.
The function attempts to print the decimal conversion of a but the second recursive call produces extra output.
The function will indeed produce no output for values below 10, which might not be the expected behavior. Without the second recursive call the output would be 1234.
You should use this instead:
void fun(int a) {
if (a >= 10)
fun(a / 10);
printf("%d", a % 10);
}
Note however that the above function only works for positive values.
You can implement this is 3 different ways:
Either make the recursive call before you start printing. If so the printing starts from the deepest level of recursion. This is very inefficient but ensures that you get the expected order 1,2,3... Generally, a recursive function that doesn't have the recursive call at the very end is an incorrect solution to any problem.
Or make the recursive calls after you print. This would lead to everything getting printed backwards as you've currently written the function. However, a recursive function with the call at the end, so-called "tail call", can sometimes get optimized into nearly as efficient code as a loop. You could probably do this here too, if you come up with a different algorithm.
Or you can implement it as a loop. Super-fast, super-readable, no risk of excessive stacking, no overhead. This is the correct solution in some 99% of all cases and the correct solution in 100% of all cases a beginner might be facing.

Can this code be called Recursion. If not, which is more advanatgeous, given below code or recursion?

I am having difficulty finding how recursion works. Some text books
says that "Recursion is when a function calls itself again and again
until some base condition is satisfied".
Some books says that "Recursion is when a function calls another
function again and again till some base condition is satisfied".
Which is true? If both are true, can we consider below given example
as a Recursion? If NO, then which is better in terms of performance,
below code or recursion?
def Function1()
{
/* do something */
}
def Function2()
{
for(i=0; i<=10; i++)
{
call Function1()
}
}
As it is, the code shows iterative calls to Function1(), if within the body of Function1() there is a call to Function2(), then it would be an indirect recursion - a function calling second function, which then calls the first again.
In general, a recursive function calls itself, either directly or indirectly. In direct recursion function, foo(), makes another call to itself. In indirect recursion, function foo() makes a call to function moo(), which in turn calls function foo(), until the base case is reached. (and then, the final result is accumulated in the exact reverse order of the initial recursive function call.)
Now, to answer your question:
Can this code be called Recursion. If not, which is more advanatgeous, given below code or recursion?
No. Iteration lacks multiple activation records (or stack frames), which makes it a better alternative.
Recursion should be used according to requirement and when you know the base condition and don't know how many times your loop should be called.
Recursion can be of different types like there can be normal recursion, infinite recursion, indirect recursion etc.
A normal recursion means calling the same function itself until a base condition is satisfied
An infinite recursion is where there will not be any base condition.
An indirect recursion is like when a calls b and b calls c and c calls back a then 'a' is being called indirectly.
Example of basic recursion:
foo()
{
base_condition;
return;
foo();
}
main()
{
foo();
}
Your example base condition can be variable equals runs for 10 times.
fun(int x)
{
if(x == 0)
return;
fun(--x);
}
main
{
fun(10);
}
Please look into the below URL for performance criteria.
performance between looping and recursion
Recursion is when
The control flow passes from a function into the very same function (directly or indirectly) repeatedly without returning first.
In your example, Function1is repeatedly called from Function2, but does return from each call before being called again, so it's not recursively called.
Let me put the pieces together: The code you provided could be recursive or it couldn't. This depends on the fact whether Function1 calls Function2. If this is the case, then you would have a mutual exclusion recursion, as pointed out by EOF.
However, this is a case that does not occur as often as normal recursion (except in pure functional environments). A normal recursion simply consists of a function which calls itself (insteaf of another function).
For further explanations and an introduction how, e. g., the recursive factorial works, see here.
Recursion occurs when a thing is defined in terms of itself or of its
type. Recursion is used in a variety of disciplines ranging from
linguistics to logic. The most common application of recursion is in
mathematics and computer science, where a function being defined is
applied within its own definition. While this apparently defines an
infinite number of instances (function values), it is often done in
such a way that no loop or infinite chain of references can occur.
Source.
So, if you have a foo and in order to calculate or execute foo, you need to recur to foo at least once more, then you have a recursion. Example:
n! = 1 * 2 * 3 * ... * n
This is an iterative definition:
int fact(n) {
int ret = 1;
int i = 1;
while (++i < n) ret *= i;
return ret;
}
This is a recursive definition:
int fact(n) {
return (n == 1) ? 1 : (n * fact(n - 1));
}
Since your code calculates Function2 with multiple usages of Function1, it is not recursive, since you did not need to call Function2 in order to evaluate Function2, nor did you need to call Function1 in order to evaluate Function1. Recursion occurs when something is its own dependency, while your code has a function which depends on another function. Your question about performance is next to impossible to answer, since there are infinite ways to implement a thing with or without recursion, when you compare a recursive approach with a non-recursive approach, then you need to have concrete implementations, or at least very strict ideas of how the two cases would be implemented. However, in general it is a good idea to prefer non-recursive approaches, as recursive approaches often have problems with the stack part of the memory, including stack overflow or infinite function calls and crashes due to bugs.
Recursion is when a function calls itself, either directly or indirectly.
Normally in the C-like languages we use recursion only when the data is tree-like. For example, you have a tree consisting of nodes, with a "next" member to indicate siblings and a "child" member to indicate children (maybe it's an XML file, or a directory tree). You want the the number of nodes so
int getNodes(Node root)
{
int answer = 1;
for(sib = root.next; sib != null; sib = sib.next)
{
answer += 1;
if(sib.child != null)
answer += getNnodes(sib.child);
}
if(node.child != null)
answer += getNodes(node.child);
return answer;
}
You can make the code a bit neater but less efficient by return 0 if root == null.
However you can use recursion for iteration. Think of it as delivering letters to a street. You can go down the street removing letters from your sack (iteration). Or you can deliver letters to the first house in the street, declare the street to be one house shorter, and repeat until the street disappears (recursion). The latter seems eccentric, but it has some advantages for automatic checking of algorithm correctness. If you forget to increment it you can't get stuck in an infinite loop, for example.

Why is Haskell so slow compared to C for Fibonacci sequence?

I am just beginner in Haskell. And I writing a code to display the N numbers in the Fibonacci sequence. Here is my code in Haskell,
fib_seq 1 = 1:[]
fib_seq 2 = 1:1:[]
fib_seq n = sum(take 2 (fib_seq (n-1))):fib_seq (n-1)
When I run this code for higher numbers like fib_seq 40 in GHCI, it takes a long time to evaluate it and my computer hangs and I have to interrupt. However, when I write the same exact logic in C, (I just print instead of saving it in the list),
#include<stdio.h>
int fib_seq (int n){
if(n==1) return 1;
else if(n==2) return 1;
else return fib_seq(n-1)+fib_seq(n-2); }
void print_fib(int n){
if(n==0) return;
else printf("%i ", fib_seq(n));
print_fib(n-1); }
int main(int argn, char* argc){
print_fib(40);
return 0; }
The code is very fast. Takes about 1 second to run when compiled with GCC. Is Haskell supposed to be this slow than C? I have looked up other answers on the internet and they say something about memoization. I am beginning Haskell and I don't know what that means. What I am saying is that the C code and Haskell code I wrote both do the same exact steps and Haskell is so much slower than C, it hangs my GHCI. A 1-2 seconds difference is something I will never worry about, and if C also had taken the same exact time as Haskell, I would also not worry about. But Haskell crashing and C doing it in 1 seconds is unacceptable.
The following program, compiled with ghc -O2 test.hs, is +/-2% the speed of the C code you posted, compiled with gcc -O2 test.c.
fib_seq :: Int -> Int
fib_seq 1 = 1
fib_seq 2 = 1
fib_seq n = fib_seq (n-1) + fib_seq (n-2)
main = mapM_ (print . fib_seq) [40,39..1]
Some comments:
Unlike you, I implemented the exact same logic. I doubt this is the real difference, though; see the remaining comments for much more likely causes.
I specified the same types as C uses for the arithmetic. You didn't, which is likely to run into two problems: using Integer instead of Int for largenum arithmetic, and having a class-polymorphic type instead of a monomorphic one adding overhead on every function call.
I compiled. ghci is built to be interactive as quickly as possible, not to produce quick code.
I don't have the right version of llvm installed at the moment, but it will often crunch through heavily-numeric code like this much better than ghc's own codegen. I wouldn't be too surprised if it ended up being faster than gcc.
Of course using one of the many well-known better algorithms for fibonacci is going to trump all this nonsense.
Guess what happens if "fib_seq (n-1)" is evaluated twice on each recursion.
And then try this:
fib_seq 1 = 1:[]
fib_seq 2 = 1:1:[]
fib_seq n = sum(take 2 f):f
where f = fib_seq (n-1)

Find steps to find given value of index

I am new to SO - I have a question which I was asked in interview and which for life of me I am not able to wrap my head around. I can solve it with while/for loop but interviewer specifically asked not to use them I even discussed with few friends of mine but unable to solve it. If someone can provide pointers.
Question is:
for given array
s[] = {5,1,0,4,2,3}
length of array is not given.
If length of array is 5 content
is guaranteed to be between 0 to 5.
There is no repetition of
numbers.
Sample example length(s, 3)
- a[3] = 4 , a[4] = 2, a[2] = 0, a[0] = 5, a[5] =3 returns length of 4 .
For given condition write subroutine int length (s, 3) - to find the number of steps it takes to find given value -
Additional conditions
You cannot use any loop statements like for, while and so on -
You cannot use any global or static variables.
You cannot call other routines inside this routine
You cannot modify given function parameters - it stays length (s, n) only
You cannot change original array too
Alternative solution that does not modify the array at all, but hides an extra parameter inside top 16 bits of x:
int length(int *s, int x){
int start = (x >> 16) - 1;
if (start < 0)
start = x;
if (s[x] == start)
return 0;
return 1 + length(s, ((start + 1) << 16) + s[x]);
}
This will fail if there are too many elements in the array, but I suspect any other recursive solution is likely to hit a stack overflow by that point in any case.
I think I found the answer eventually no I didnt crack it but found it online :) .. Here is the solution
int length(int * s, int x){
if(s[x] < 0){
return -1;
}
else{
s[x] = -s[x];
int len = length(s, -s[x]);
s[x] = -s[x];
return len + 1;
}
}
i don't think it contradicts with any of your conditions. i just didn't use the array as a parameter (that isn't a problem actually, you can modify it yourself)
int s[] = {5,1,0,4,2,3};
bool col[100]; ///to check cycle
int rec(int n)
{
if(col[n])return 0;
col[n]=true;
int sum=0;
sum = 1+rec(s[n]);
return sum;
}
The interviewer is probing your understanding of algorithms and programming paradigms, trying to understand your training, background, and depth. The interviewer has a challenging task; identifying capable developers with minimal evidence. Thus the interviewer presents a constructed problem that (they hope) elicits the desired knowledge (does candidate X know how to solve problem Y, or understand concept Z) perhaps because the interviewer believes the desired answer indicates the candidate knows the expected body of knowledge.
Modern languages provide several repetition structures (commands, statements), some which pre-test (check condition before entering statement-block), and some which post-test (check condition after performing statement block at least once). Here are examples,
Pre-test
while(condition) statement-block
for(initializer;condition;step) statement-block
Post-test
do statement-block while(condition)
repeat statement-block until(condition)
do statement-block until(condition)
These can all be written as conditional (choice) structures with branching (goto),
Pre-test
label:
if(condition)
statement-block;
goto label;
else
nil;
endif
Post-test
label:
statement-block;
if(condition)
goto label;
endif
You can also use recursion, where you call the same function as long as condition holds (or until condition met, depending upon positive or negative logic),
Pre-test
function recurse(args)
if(condition)
statement-block
recurse(revised args);
endif
return
end #function
Post-test
function recurse(args)
statement-block
if(condition)
recurse(revised args);
endif
return;
end
You would learn about recursion in an algorithms, or perhaps a computability course. You would learn about conditional branching in a compiler, high performance computing, or systems class. Your compiler course might examine techniques for detecting 'tail-recursion', and how to rewrite the function call into a loop.
Here is the problem, restated,
given array, s[] = {5,1,0,4,2,3}
array length unknown
content between [0 .. length], not repeated, no duplicates
write subroutine which provides the number of steps to find given value
That is,
int length( array s, int member ) --> position
Examine the conditions (constraints) on the problem,
Array length unknown - Solution must work for variable range of inputs
Cannot use loop statements (for, while, etc) - This suggests either the interviewer wants conditional branch or recursion.
Cannot use global or static variables - Does this suggest interviewer wants a recursive/functional-programming solution? Conditional-branch also provides this.
Cannot call other routines inside this routine - Does interviewer mean functions other than same function, or call any function (what does interviewer mean by 'other').
Cannot modify function parameters, stays length(s,n) - Declaring local (stack) variables is allowed. This could mean pass by value, make a local copy, etc. But not destructive modifications.
Cannot change original array - Definitely no destructive modifications. Possible 'hint' (ok to make local copy?), or further indication that you should use conditional-branch?
Here are two solutions, and a test driver (note, I have named them lengthi, iterative, and lengthr, recursive).
#include <stdio.h>
/* conditional branch */
int lengthi( int s[], int member )
{
int position=0;
AGAIN:
if( s[position] == member ) return(position);
++position;
goto AGAIN;
return(-1);
}
/* recursive */
int lengthr( int s[], int member )
{
if( s[0] == member ) return(0);
return( 1+length(s+1,member) );
}
int
main(int argc,char* argv[])
{
int s1[] = {0,1,2,3,4,5,6,7,8,9};
int s2[] = {1,2,3,4,9,8,7,6,0,5};
int s3[] = {2,4,6,8,0,1,3,5,7,9};
printf("%d at %d\n",3,lengthr(s1,3));
printf("%d at %d\n",3,lengthr(s2,3));
printf("%d at %d\n",3,lengthr(s3,3));
printf("%d at %d\n",3,lengthi(s1,3));
printf("%d at %d\n",3,lengthi(s2,3));
printf("%d at %d\n",3,lengthi(s3,3));
}
Since we are supposed to find the number of steps (iterations, function calls), that is asking for the ordinal position in the list, not the C index (zero based) position.
This is an interview question, and not a programming problem (per se), so probably better suited for the Programmers.stackexchange site. I might give the interviewer an entertaining answer, or their desired answer.

difficulty in understanding successive recursive calls

I am trying to understand the following program in which successive recursion function calls are present, but getting confused while tracing how the tack gets loaded.
void func(char*); // function prototype
int main(){
func("123");
return 0;
}
void func(char a[]){
if(a[1]=='\0')
return;
func(a+1);
func(a+1);
printf("%c",a[1]);
}
the output for this is 3 3 2
would appreciate if someone could advise on this one...
does this kind of multiple recursive calls beneficial in any way or find application in specific problem areas..?
Just put yourself in the position of the CPU and step through line-by-line (or use a debugger to help with that task).
The first call is to
func("123")
this call does not satisfy the termination condition a[1] == '\0', so it calls
func("23");
The call to func("23") in turn calls
func("3")
which DOES satisfy the return condition. So, that call returns to the previous caller, func("23").
func("23") proceeds to make another call to func("3") due to the lines
func(a+1);
func(a+1);
Continue this process of executing the program in your mind, and write down what would be in each call to printf. That will explain your output.
UPDATE
Note that the call to printf() happens after the recursive calls, so e.g. a call to
func("123")
would proceed like
Enter func("123")
Termination condition not met
Call func("23")
Call func("23") again
Printf("3") (which is a[1])
Return
Debugging with breakpoints is one way to understand recursion. Another way is to draw the tree of recursive calls.
From the figure, In every level after level0, the printf statement occurs after every two nodes owing to these two lines of code:
func(a+1);
func(a+1);
In general, this becomes a perfect binary tree for any input string of length greater than 0. The total number of nodes is given by this formula:
2^(k+1) - 1 // k is the depth; here k = 2
Total number of printf statements executed can be obtained by this formula:
2^k - 1 // For k=2, there will be 3 printf statements each printing 3,3,2 respectively
the posted code is a rather poorly designed instance of recursion.
The following code has the correct 'tail' form of recursion.
It could be made even better by passing the reversed string back to main and let main print it.
It reverses the order of the string passed to func() by main()
Please, when asking about a runtime problem, post code the compiles, including the necessary #includes for header files so we are not guessing about which headers to include
#include <stdio.h>
void func(char*); // function prototype
int main(){
func("123");
return 0;
}
void func(char a[])
{
if(a[1]=='\0') // check for end of recursive sequence
{
printf( "%c", a[0] ); // last tail action
return;
}
func(a+1); // step+next recursion
printf( "%c", a[0] ); // tail action
return;
}
The recursion can be simply understood as follows.
For example:
Func(int a){
while(a>1)
return a * func(a-1);
}
Suppose a = 5.
What happens is that it returns 5 * func(4).
Now func(4) returns 4 * func(3) and it goes on like this.
Check out this example for use of recursion in fibonacci series.

Resources