I have this program
//h is our N
static int g=0;
int fun(int h){
if(h<=0){
g++;
return g;
}
return g+fun(h-1)+fun(h-4);
}
Is it possible to speed it up using dynamic programming?
I figured out that this function runs in O(2^n)
I am supposed to reduce the running time by dynamic programming, but do not understand the concept.
Just asking for a nudge in the right direction.
While I can't give an answer to your actual question, I am intrigued by something altogether different, namely the statement
return g+fun(h-1)+fun(n-4);
Obviously, your function has the side effect of changing the global static variable g. I am not 100% sure whether the return statement's expression actually evaluates in a clearly defined fashion, or whether the result might be undefined.
It might be a nice exercise to think about the order in which those function calls are executed, and how this affects g and thereby the function's result.
If we define that summation order in g+fun(h-1)+fun(n-4) is from left to rigth, than this is good defined problem. With that I get values for fun(n), n=1,...,15:
3, 6, 10, 15, 33, 74, 154, 295, 575, 1143, 2269, 4414, 8508, 16396, 31634
Return value of fun(n) is evaluated as sequence of summations with not-descending elements. Each summand is for one larger then previous (return g++;) or same as previous (return g+fun()+fun()). Execution sequence of return statements depend only of fun() input parameter. So, with g set to initial value != 0 we get same summands as with g=0, but every summand is larger for same initial value.
With that, fun(n) with initial g > 0 will return value that is g * number of executed return statements larger than with initial g = 0.
Define A(n) as number of executed return statements while executing fun(n), and G(n) number of executed return statement in if clause (same as number of g++ statement executions). For A and G holds:
A(n) = A(n-1) + A(n-4) + 1
G(n) = G(n-1) + G(n-4)
A(n) = 1 and G(n) = 1, for n <= 0
From these observations it can be seen that for n > 0 holds:
fun(n) = fun(n-1) + G(n-1) * A(n-4) + fun(n-4)
Simple python implementation:
def x( h ):
Rg = { -3:1, -2:1, -1:1, 0:1 }
Ra = { -3:1, -2:1, -1:1, 0:1 }
F = { -3:1, -2:1, -1:1, 0:1 }
for i in xrange( 1, h+1 ):
F[i] = F[i-1] + Rg[i-1]*Ra[i-4] + F[i-4]
print i, F[i]
Rg[i] = Rg[i-1] + Rg[i-4]
Ra[i] = Ra[i-1] + Ra[i-4] + 1
#stakx: for expression g+fun(h-1)+fun(h-4) we can't have evaluation order guaranty, especially not in C.
Yes , It's possible to use DP to speed it up and avoid using CPU stack, but I agree with stakx about the side effect of changing the global static variable g.
It's better to provide a mathematical expression because the recursive function above could give a different result depending on the order & count of calls.
OK. We start from fun (a serialized version where order of evaluation is forced).
int fun(int h){
if(h<=0){
g++;
return g;
}
int tmp1 = g;
int tmp2 = fun(h-1);
int tmp3 = fun(h-4);
return tmp1+tmp2+tmp3;
}
Let's focus on g and forget the current result of the function
Now it is easy to change the function to pass in g as a parameter and to return the new value of g as a result.
int gun(int h, int g0){
if(h<=0){
return g0+1;
}
int tmp1 = g0;
int tmp2 = gun(h-1, g0);
int tmp3 = gun(h-4, tmp2);
return tmp3;
}
What can be simplified into:
int gun(int h, int g0){
if(h<=0){
return g0+1;
}
return gun(h-4, gun(h-1, g0));
}
Now back to fun:
int fun2(int h, int g0){
if(h<=0){
return g0+1;
}
return g0+fun2(h-1, g0)+fun2(h-4, gun(h-1,g0));
}
fun2 does exactly the same thing as the initial fun, but now as we removed the side effect and the function only depends from it's parameter, we can memoize results (store already computed results in an array), which should speed-up the computing.
We can still simplify gun a bit. The g0 parameter is not really necessary, let's set it to 0.
int gun2(int h){
if(h<=0){
return 1;
}
return gun2(h-4) + gun2(h-1);
}
We may even define a fun3 with g0 parameter fixed to 0, henceforth a bit simpler, but it still has to call fun2. I do not see yet how to simplify further but it's probably possible.
int fun3(int h){
if(h<=0){
return 1;
}
return fun3(h-1)+fun2(h-4, gun2(h-1));
}
Related
I recently learn the basic of C++. And i found something that i didn't get the idea. Here is the program that make me a little confuse.
#include <iostream>
using namespace std;
int main()
{
int m = 4, n;
n=++m*--m;
cout <<"m="<<m<<" and n="<<n<<"\n;
return 0;
}
And the output is m=4 and n=16.
I thought that
m=4, so ++m is 5, and --m will be 4,
then n= 5*4= 20.
Hence, the m=4 and n=20.
I think mine is false. So i need a help. Thank you.
The operands of * are unsequenced relative to each other. This means that not only may they be evaluated in any order; but if each operand contains multiple sub-steps, the sub-steps of one operand might be interleaved with those of the other operand.
An example of this might be (f() + g()) * (h() + i()) . The four functions could be called in any order -- it is not required that f and g are called together, etc.
Back to your example, the following two sub-steps are unsequenced relative to each other:
writing the new value to m, as part of ++m
reading m, as part of --m
When there are two unsequenced operations on the same variable (and at least one of them is a write), it is undefined behaviour which means anything can happen (including unexpected results).
This:
n=++m*--m;
is bad code. Replace it with something clear, such as:
n = (m + 1) * (m - 1);
The original code, for complicated reasons, may not do what you expect, so it's better not to write such code in the first place. If you want to know more about the nitty gritty details of why this is, see here: Undefined behavior and sequence points
++m means "increment m then use its value" The current call with have (m + 1) as value.
m-- means "use the value of m, then decrement it" The current call with have the original value of m, and subsequent calls will have (m - 1) as value
If that makes it any clearer for you, you can also rewrite it as:
int m = 4, n;
n = (m = (m + 1)) * (m = (m - 1));
I am pretty positive the operation occurs before the increment. That is why that is happening. If you break it down like this, it should work.
The answer should be 15 because 4 + 1 is 5 and 4 - 3 is 3, thus 5 * 3 is 15. See below
int main()
{
int m = 4, n;
int g;
n = (m+1) * (m-1);
std::cout << "m=" << m << " and n=" << n << "\n" ;
std::cin >> g;
return 0;
}
Might be a very basic question but I just got stuck with it. I am trying to run the following recursive function:
//If a is 0 then return b, if b is 0 then return a,
//otherwise return myRec(a/2, 2*b) + myRec(2*a, b/2)
but it just gets stuck in infinite loop. Can anybody help me to run that code and explain how exactly that function works? I built various recursive functions with no problems but this one just drilled a hole in my head.
Thanks.
Here is what I tried to do:
#include<iostream>
int myRec(int a, int b){
if (a==0){
return b;
}
if (b==0){
return a;
}
else return myRec(a/2, 2*b) + myRec(2*a, b/2);
}
int main()
{
if (46 == myRec(100, 100)) {
std::cout << "It works!";
}
}
Well, let us mentally trace it a bit:
Starting with a, b (a >= 2 and b >= 2)
myRec(a/2, 2*b) + something
something + myRec(2*a', b'/2)
Substituting for a/2 for a' and 2*b for b', we get myRec(2*(a/2), (b*2)/2), which is exactly where we started.
Therefore we will never get anywhere.
(Note that I have left out some rounding here, but you should easily see that with this kind of rounding you will only round down a to the nearest even number, at which point it will be forever alternating between that number and half that number)
I think you are missing on some case logic. I last program in C ages ago so correct my syntax if wrong. Assuming numbers less than 1 will be converted to zero automatically...
#include<iostream>
int myRec(int a, int b){
// Recurse only if both a and b are not zero
if (a!=0 && b!=0) {
return myRec(a/2, 2*b) + myRec(2*a, b/2);
}
// Otherwise check for any zero for a or b.
else {
if (a==0){
return b;
}
if (b==0){
return a;
}
}
}
UPDATE:
I have almost forgot how C works on return...
int myRec(int a, int b){
if (a==0){
return b;
}
if (b==0){
return a;
}
return myRec(a/2, 2*b) + myRec(2*a, b/2);
}
VBA equivalent with some changes for displaying variable states
Private Function myRec(a As Integer, b As Integer, s As String) As Integer
Debug.Print s & vbTab & a & vbTab & b
If a = 0 Then
myRec = b
End If
If b = 0 Then
myRec = a
End If
If a <> 0 And b <> 0 Then
myRec = myRec(a / 2, 2 * b, s & "L") + myRec(2 * a, b / 2, s & "R")
End If
End Function
Sub test()
Debug.Print myRec(100, 100, "T")
End Sub
Running the test in Excel gives this (a fraction of it as it overstacks Excel):
T: Top | L: Left branch in myRec | R: Right branch in myRec
The root cause will be the sum of the return which triggers more recursive calls.
Repeating of the original values of a and b on each branch from level 2 of the recursive tree...
So MyRec(2,2) = MyRec(1,4) + MyRec(4,1)
And MyRec(1,4) = MyRec(.5,8) + MyRec(2,2)
So MyRec(2,2) = MyRec(.5,8) + MyRec(2,2) + MyRec(4,1)
Oops.
(The .5's will actually be zeroes. But it doesn't matter. The point is that the function won't terminate for a large range of possible inputs.)
Expanding on gha.st's answer, consider the function's return value as a sum of expressions without having to worry about any code.
Firstly, we start with myRec(a,b). Let's just express that as (a,b) to make this easier to read.
As I go down each line, each expression is equivalent, disregarding the cases where a=0 or b=0.
(a,b) =
(a/2, 2b) + (2a, b/2) =
(a/4, 4b) + (a, b) + (a, b) + (4a, b/4)
Now, we see that at a non-terminating point in the expression, calculating (a,b) requires first calculating (a,b).
Recursion on a problem like this works because the arguments typically tend toward a 'base case' at which the recursion stops. A great example is sorting a list; you can recursively sort halves of the list until a list given as input has <= 2 elements, which is trivial without recursion. This is called mergesort.
However, your myRec function does not have a base case, since for non-zero a or b, the same arguments must be passed into the function at some point. That's like trying to sort a list, in which half of the list has as many elements as the entire list.
Try replacing the recursion call with:
return myRec(a/2, b/3) + myRec(a/3, b/2);
I'm new to concept of recursion. I want to write a recursive function which take a float and integer as argument and call it recursively in a way that the float value remain constant and integer value changes
I write the following code:
#include <stdio.h>
float sum(float f, int k)
{
static float c;
c = f - k;
c = sum(f, k - 1);
return c;
}
int main()
{
float f, g = 10.00;
int i = 5;
f = sum(g, i);
printf("the sum of integer and float = %f", f);
}
When I compile it it shows no errors but when I run the program it shows a segmentation fault.
My question are following:
what is wrong with the code?
why it is showing segmentation error?
how to use recursion in a function which has more than one argument?
Please explain me with some example of recursive function which has two arguments.
The code is wrong because it can never end (I presume it fails with a stackoverflow error).
For recursion, you need two things
A base case
A recursive case that moves towards the base case
Looks like you've only got the second. I suspect sum should return when k is zero. Something like this hopefully makes sense:
float sum(float f, int k) {
if (k <= 0) {
// The base case
return f;
} else {
// The recursive case. This does one step of the work
// and moves towards the base case
return 1 + sum(f, k - 1);
}
}
Your recursion does not have a base (non-recursive), terminating case.
Every call to sum makes a recursive call to itself, this continues till your stackoverflows, resulting in a seg fault.
The recursion never stops, and eventually you run out of stack. You need to decide when it is time to stop the recursion. for example, if k equals 0 you don't call sum again, but exit with return.
float sum(float f ,int k)
{
static float c;
if (k > 0)
{
c=f-k; /// <<< why is this here? you ignore the value and overwrite it in the next step.
c=sum(f,k-1);
}
return c;
}
Of course there are additional problems: having c as static may be a problem that will affect the correctness of the calculation, and also the place I marked looks suspicious because you loose the value and overwrite it with the subsequent call to sum.
How about this?
#include <stdio.h>
float sum(float f, int k, float c) {
if (k == 0)
return c;
sum(f, k - 1, f - k);
}
The first thing I see is that your recursion has no termination. It will go on forever. Perhaps you want:
float sum(float f ,int k)
{
static float c;
c=f-k;
if (k != 0)
c=sum(f,k-1);
return c;
}
So that when k is zero the recursion stops. You had a stack overflow.
When you do recursion you need a status to end it.
So your code with changes:
#include <stdio.h>
float sum(float f, int k)
{
if(k == 0) return f;
return 1 + sum(f,k-1);
}
int main()
{
float f, g = 10.00;
int i = 5;
f = sum(g, i);
printf("the sum of integer and float = %f", f);
}
With that code, and your example f=10.00 and i=5
Call sum(10.0, 5)
return 1 + sum(10.0, 4)
1 + sum(10.0, 3)
1 + sum(10.0, 2)
1 + sum(10.0, 1)
1 + sum(10.0, 0)
10
1 + 10 = 11
1 + 11 = 12
1 + 12 = 13
1 + 13 = 14
1 + 14 = 15
return 15;
I don't understand what the "sum" function is for. Is it supposed to be adding f and k? In which case, there is no recursion; you should just add f and k: return f + k.
But to try to answer your questions:
There is no base case. This is the cause of the infinite recursion. Every recursive function needs a base case which is a condition under which it does not recurse. Your function recurses no matter what; therefore it will always recurse forever.
When recursion segfaults, it's usually due to a stack overflow (no pun intended); it means you are recursing forever and eventually running out of space.
You can use recursion in a function with more than one argument, just the same as any other function. Just call it with whatever the new values are for the next iteration.
Note that you often have a "constant" value, that doesn't change during the recursion. To do that, you just pass the value unchanged on the recursive call, so the same value is available at each step.
I have the following function:
int mult(int y, int z)
{
if (z == 0)
return 0;
else if (z % 2 == 1)
return mult(2 * y, z / 2) + y;
else
return mult(2 * y, z / 2);
}
What I need to do is prove its correctness by induction. Now the trouble I'm having is that even though I know it works since I ran it I can't follow each individual step.
What is confusing me is that y only shows up as an argument and in no place does it show up in a return except in the recursive part, and yet the function actually returns y as the answer.
How does this happen? I need to be able to follow everything that happens so that I can do the iterations of it for the proof.
Since this is obviously a homework question, I recommend you do what the assinment was likely meant fot you to do. Trace through the code.
1) give a starting value for y and z.
2) either on paper or in a debugger, trace what happens when you call the function.
3) repeat step 2 with your current y/z values until program completion.
#include <iostream>
using namespace std;
int mult(int y, int z)
{
if(z==0) {
cout<<"z is null! - y:"<<y<<" z: "<<z<<endl;
return 0;
}
else if (z%2==1)
{
cout<<"z is odd! - y:"<<y<<" z: "<<z<<endl;
// make z even
return mult(2*y,z/2)+y;
}
else
{
cout<<"z is even! - y:"<<y<<" z: "<<z<<endl;
return mult(2*y,z/2);
}
}
int main() {
cout<<"result: "<<mult(3,13)<<endl;
}
Output:
z is odd! - y:3 z: 13
z is even! - y:6 z: 6
z is odd! - y:12 z: 3
z is odd! - y:24 z: 1
z is null! - y:48 z: 0
result: 39
How it works for 3 and 13:
There's a switch for even and odd numbers (see comment in code).
When z is null, the recursion "starts to return to the initial call". If the number z is odd it adds y to the returned value of the recursive call, if it's even it justs returns the value from the recursive call.
odd: return 0 + 24
odd: return 24 + 12
even: return 36
odd: return 36 + 3
step-by-step analisis
final result: 100
mult(10, 10)
{
makes 100
mult(20, 5)
{
makes 100
mult(40, 2) + 20
{
makes 80
mult(80, 1)
{
makes 80
mult(160, 0) + 80
{
return 0;
}
}
}
}
}
Note: If this is homework, tag it as such.
So, we basically got three recursive cases. To make it all clearer, I'd rewrite the C-code into some functional pseudo-code. Replace mult with an intuitive operator sign and figure out descriptive explanations of low-level expressions like (z%2==1).
You'll come up with something like
a ** b =
| b is 0 -> 0
| b is even -> 2a ** (b/2)
| b is odd -> 2a ** (b/2) + a
Do you get the point now?
One approach would be to translate each line into "English". My translation would be something like this:
if z is zero, return zero
if z is odd, return mult(y*2, z/2) + y
if z is even, return mult(y*2, z/2)
The general pattern is to recursively call mult with the first parameter doubling, and the second parameter halving.
Note that here you're calling mult with z/2, but its arguments are integers, so if your function continues to recurse, the 2nd parameter will halve each time until it gets down to 1, and then finally 1/2 which rounds down to 0 - at which point recursion will stop because z==0.
With those clues, you should be able to understand how this algorithm works.
Demonstrations by induction are based on proving that the result is valid for the first value, and that if the principle is correct for a generic value N, it is provable that it holds for N+1.
To simplify, you can start by proving that it works for z in { 0, 1, 2 } which should be trivial with a manual test. Then to demonstrate the induction step, you start with a generic z=N, and prove that if mult( y, N ) is a valid result, then mult( y, N+1 ) is also a valid result in terms of the previous one. Since there are different branches for even and odd numbers, you will have to prove the induction step for both even and odd N numbers.
ya = ya
a = an even number
b = the next odd number (in other words a + 1)
So, if you want the equation above in terms of only even numbers (an 'a') when given an odd number (a 'b') you can do the following:
yb = y(a+1) = y*a + y
Now confuse everyone by writing 'a' as 2*(z/2).
y*a becomes (2*y)*(z/2)
y*b becomes ((2*y)*(z/2))+y
Since 'z' appears in the formula for both even and odd numbers, we want to think that the code is telling us that (2*y)*(z/2) = (2*y)*(z/2) + y which is obviously MADNESS!
The reason is that we have snuck in the fact that z/2 is an integer and so z can never be odd. The compiler will not let us assign z/2 to an integer when z is odd. If we try to make 'z' odd, the integer we will really be using is (z-1)/2 instead of z/2.
To get around this, we have to test to see if z/2 is odd and pick our formula based on that (eg. either ya or yb in terms of 'a').
In mult(y,z) both 'y' and 'z' are both integers. Using the symbols above mult(2*y,b/2) becomes mult(2*y,a/2) because b/2 will be truncated to a/2 by the compiler.
Since we are always going to get an 'a' as a parameter to 'mult', even when we send a 'b', we have to make sure we are only using formulas that require 'a'. So, instead of yb we use ya+1 as described above.
b/2 = a/2 + 1/2 but 1/2 cannot be represented as part of an int.
Not really an answer, but more of a suggestion.
You may want to reduce the recursion call from 2 to one:
int mult(int y, int z)
{
int result = 0;
if (z == 0)
return result;
result = mult(2 * y, z / 2); // Common between "then" and "else"
if ((z % 2) == 1)
{
result += y;
}
return result;
}
This could be simplified once more by observing the rule "one exit point only":
int mult(int y, int z)
{
int result = 0;
if (z != 0)
{
result = mult(2 * y, z / 2); // Common between "then" and "else"
if ((z % 2) == 1)
{
result += y;
}
}
return result;
}
Although many compilers will perform this simplification automatically, debugging is usually easier when the code is simplified. The debugger will match the code when single-stepping.
Sometimes simplifying will add clarity. Also, adding comments will help you figure out what you are doing as well as the next person who reads the code.
I was calculating the Fibonacci sequence, and stumbled across this code, which I saw a lot:
int Fibonacci (int x)
{
if (x<=1) {
return 1;
}
return Fibonacci (x-1)+Fibonacci (x-2);
}
What I don't understand is how it works, especially the return part at the end: Does it call the Fibonacci function again? Could someone step me through this function?
Yes, the function calls itself. For example,
Fibonacci(4)
= Fibonacci(3) + Fibonacci(2)
= (Fibonacci(2) + Fibonacci(1)) + (Fibonacci(1) + Fibonacci(0))
= ((Fibonacci(1) + Fibonacci(0)) + 1) + (1 + 1)
= ((1 + 1) + 1) + 2
= (2 + 1) + 2
= 3 + 2
= 5
Note that the Fibonacci function is called 9 times here. In general, the naïve recursive fibonacci function has exponential running time, which is usually a Bad Thing.
This is a classical example of a recursive function, a function that calls itself.
If you read it carefully, you'll see that it will call itself, or, recurse, over and over again, until it reaches the so called base case, when x <= 1 at which point it will start to "back track" and sum up the computed values.
The following code clearly prints out the trace of the algorithm:
public class Test {
static String indent = "";
public static int fibonacci(int x) {
indent += " ";
System.out.println(indent + "invoked with " + x);
if (x <= 1) {
System.out.println(indent + "x = " + x + ", base case reached.");
indent = indent.substring(4);
return 1;
}
System.out.println(indent + "Recursing on " + (x-1) + " and " + (x-2));
int retVal = fibonacci(x-1) + fibonacci(x-2);
System.out.println(indent + "returning " + retVal);
indent = indent.substring(4);
return retVal;
}
public static void main(String... args) {
System.out.println("Fibonacci of 3: " + fibonacci(3));
}
}
The output is the following:
invoked with 3
Recursing on 2 and 1
invoked with 2
Recursing on 1 and 0
invoked with 1
x = 1, base case reached.
invoked with 0
x = 0, base case reached.
returning 2
invoked with 1
x = 1, base case reached.
returning 3
Fibonacci of 3: 3
A tree depiction of the trace would look something like
fib 4
fib 3 + fib 2
fib 2 + fib 1 fib 1 + fib 0
fib 1 + fib 0 1 1 1
1 1
The important parts to think about when writing recursive functions are:
1. Take care of the base case
What would have happened if we had forgotten if (x<=1) return 1; in the example above?
2. Make sure the recursive calls somehow decrease towards the base case
What would have happened if we accidentally modified the algorithm to return fibonacci(x)+fibonacci(x-1);
return Fibonacci (x-1)+Fibonacci (x-2);
This is terribly inefficient. I suggest the following linear alternative:
unsigned fibonacci(unsigned n, unsigned a, unsigned b, unsigned c)
{
return (n == 2) ? c : fibonacci(n - 1, b, c, b + c);
}
unsigned fibonacci(unsigned n)
{
return (n < 2) ? n : fibonacci(n, 0, 1, 1);
}
The fibonacci sequence can be expressed more succinctly in functional languages.
fibonacci = 0 : 1 : zipWith (+) fibonacci (tail fibonacci)
> take 12 fibonacci
[0,1,1,2,3,5,8,13,21,34,55,89]
This is classic function recursion. http://en.wikipedia.org/wiki/Recursive_function should get you started. Essentially if x less than or equal to 1 it returns 1. Otherwise it it decreases x running Fibonacci at each step.
As your question is marked C++, I feel compelled to point out that this function can also be achieved at compile-time as a template, should you have a compile-time variable to use it with.
template<int N> struct Fibonacci {
const static int value = Fibonacci<N - 1>::value + Fibonacci<N - 2>::value;
};
template<> struct Fibonacci<1> {
const static int value = 1;
}
template<> struct Fibonacci<0> {
const static int value = 1;
}
Been a while since I wrote such, so it could be a little out, but that should be it.
Yes, the Fibonacci function is called again, this is called recursion.
Just like you can call another function, you can call the same function again. Since function context is stacked, you can call the same function without disturbing the currently executed function.
Note that recursion is hard since you might call the same function again infinitely and fill the call stack. This errors is called a "Stack Overflow" (here it is !)
In C and most other languages, a function is allowed to call itself just like any other function. This is called recursion.
If it looks strange because it's different from the loop that you would write, you're right. This is not a very good application of recursion, because finding the n th Fibonacci number requires twice the time as finding the n-1th, leading to running time exponential in n.
Iterating over the Fibonacci sequence, remembering the previous Fibonacci number before moving on to the next improves the runtime to linear in n, the way it should be.
Recursion itself isn't terrible. In fact, the loop I just described (and any loop) can be implemented as a recursive function:
int Fibonacci (int x, int a = 1, int p = 0) {
if ( x == 0 ) return a;
return Fibonacci( x-1, a+p, a );
} // recursive, but with ideal computational properties
Or if you want to be more quick but use more memory use this.
int *fib,n;
void fibonaci(int n) //find firs n number fibonaci
{
fib= new int[n+1];
fib[1] = fib[2] = 1;
for(int i = 3;i<=n-2;i++)
fib[i] = fib[i-1] + fib[i-2];
}
and for n = 10 for exemple you will have :
fib[1] fib[2] fib[3] fib[4] fib[5] fib[6] fib[7] fib[8] fib[9] fib[10]
1 1 2 3 5 8 13 21 34 55``