I know this is basic CS knowledge, but I still can't grasp the idea of doing a recursive function over a for loop. I'm still confused on the idea of recursion especially with numbers. Lets say there's a numerical sequence 3, 11, 27, 59, 123.... I know how to figure out the mathematical recursive sequence which is just An = An-1 + (8*(n-1)), but don't really know how to put this into a C++ recursive function.
Can someone outline the creation of a recursive function for the above numerical sequence?
Recursive functions have two "parts", the base case and the recursion. The base case is when your function stops recursing (and starts unwinding the call stack). Without the base the function just keeps calling itself until the stack overflow happens and the program is terminated by the OS.
The recursive part takes the initial problem (in your case finding the ith number in a sequence) and shrinks it. This happens until the base case is hit. So for finding the ith number in a sequence, let's say the 4th, you start looking for the 4th number, but that depends on the 3rd, which depends on the 2nd which depends on the first. The initial recursion shrinks the problem from the 4th number to the 3rd.
Here's a stab (not at all tested) at a recursive function for your sequence.
int recursive(int i) {
// This is your base case, it prevents infinite recursion.
if (i == 0) return 0; // Or whatever you base value is
else {
int sum = recursive(i-1) + 8 * (i-1);
return sum;
}
}
Lots of times a recursive function can be done with a loop. However there are functions which require recursion. For instance, Ackermann's Function. A really good video on Computerphile
Basic recursive implementation of said function (proper values for your sequence are 3, 11, 27, 51, 83, 123, … btw):
int seq(int n)
{
if (n <= 1)
return 3;
else
return seq(n-1) + 8 * (n-1);
}
However, this implementation is not tail-recursive (therefore it will use stack, while iterative implementation would not). We can write tail-recursive version by introducing accumulator parameter:
int seq_r(int n, int acc)
{
if (n <= 1)
return acc;
else
return seq_r(n-1, acc + 8 * (n-1));
}
int seq(int n)
{
return seq_r(n, 3);
}
Or, same implementation but with seq_r hidden inside your function using lambda expressions:
#include <functional>
int seq(int n)
{
std::function<int(int, int)> seq_r = [&] (int n, int acc) -> int {
if (n <= 1)
return acc;
else
return seq_r(n-1, acc + 8 * (n-1));
};
return seq_r(n, 3);
}
If your sequence function is defined as: A[n] = A[n-1] + 8*(n-1) then you need two things. 1) A structure to hold the sequence of numbers, and 2) a function or loop to produce those numbers. For the structure I will use a std::vector and the loop or function can be used as below:
Loop
#include <vector>
int main()
{
std::vector<int> storage;
// Seed the storage with a number since the sequence looks back.
storage.push_back(3);
// Define the maximum number count.
int maxNum = 5;
// Create the sequence by starting from n=1 since there are [n-1] terms.
for(int n = 1; n <= maxNum; n++)
storage.push_back(storage[n - 1] + 8*(n - 1));
return 0;
}
Function
#include <vector>
std::vector<int> storage;
void DoSequence(int maxNum, int n = 0)
{
// Check the limit.
if(n > maxNum)
return;
// Check seeding condition if adding the first element,
// otherwise run the equation.
if(n == 0)
storage.push_back(3);
else
storage.push_back(storage[n - 1] + 8*(n-1));
// Call the same function.
DoSequence(maxNum, n + 1);
}
int main()
{
// Call the recursive function with upper limit (n=5).
DoSequence(5);
return 0;
}
There are other ways to implement the details such as how storage is declared or handled but that is personal preference. Note: I did not test this code but hopefully you get the idea. In short, once you have your sequence function defined then create a loop or program function to generate the numbers.
Related
I just solved the subset sum problem:
Given an integer array nums of size N. You are also given an integer B, you need to find whether there exists a subset in nums whose sum is B. If there exist a subset then return 1 else return 0.
Constraints are: 1 <= N <= 100; 1 <= nums[i] <= 100; 1 <= B <= 10^5;
The way I solved this problem is as below (0/1 knapsack):
vector<int> n;
int t;
unordered_map<string, long long> m;
int helper(int i, int sum) {
if(i>=n.size()) return sum==t;
string str=to_string(i)+"-"+to_string(sum);
if(m.count(str)) return m[str];
int val=helper(i+1, sum+n[i]);
val=max(val, helper(i+1, sum));
return m[str]=val;
}
int Solution::solve(vector<int> &nums, int B) {
n=nums;
t=B;
m.clear();
return helper(0,0);
}
This gets "Accepted". However, note that all the values in nums are positive; so IMO sum will only remain the same/go on increasing. i goes on increasing, too. So, we will never encounter a value previously stored in the memoization table.
But, if I remove memoization, it results in Wrong Answer for some large test case. What am I missing? Will any recursive call ever encounter a previous state?
You call helper twice, the second time with the lower sum than the first. Therefore a later call to helper could indeed have the same sum as an earlier call.
#user3386109 already gave a concrete set of num that demonstrates this. As for how often, consider the case where nums = [1, 1, ..., 1] 100 times. Then without memoization you'll call helper(100, 50) 100 choose 50 = 100,891,344,545,564,193,334,812,497,256 times. Over 100 octillion calls..takes a while.
I need to make a function that calculates the average and return the number of values larger than the average. For example, passing an array of {4, 5, 12, 17} should return 2 (because 12 and 17 are larger than the average 9.5). So far I wrote the function to return the average, but how can I make it count the numbers larger than the average and keep it tail-recursive?
int TAvg(int* a, int size, int acc=0, int num=0){ //acc is the sum so far, num is the number of all elements
if (size == 0){
return (acc / num);
}
return TAvg(a, size - 1, acc+a[size-1], num+1);}
Any help would be appreciated. Thank you.
Once your tail-recursive function calculates the average on the final recursion call, and starts unwinding the call stack, as its unwinding the recursive calls it now knows what the average is.
It can now compare the average with each element, as its unwinding all the recursion calls, and increment a counter for each element is above the computed average.
EDIT: I thought of another approach that implements more of a spirit of a tail-recursive design. Have your function return a class:
class result {
public:
int average;
int counter;
result(int average, int last_value) : average(average), counter(0)
{
if (last_value > average)
++counter;
}
result(const result &prev_result, int next_value) : average(prev_result.average), counter(prev_result.counter)
{
if (next_value > average)
++counter;
}
};
Now your tail-recursive function can compute the result by:
The initial recursive call (or the last recursive call, depending on one's point of view), would construct result by using the first constructor, using the computed average, and the first/last value in the array:
return result(TAvg(computed_average_goes_here, *acc));
The remaining tail-recursive calls become:
return result( TAvg( /* resursive parameters */), *acc);
I am trying to create a recursive function as follows.
The function takes a counter k and as long that the counter is larger than zero I would like to call it recursively so that in the end I end up with something like this:
result = 2(2(2n+1)+1)+1
where the last n (when k=0) should be zero.
int pass(int k, int n)
{
if(k==0)
{
n = 0;
}
else
{
k--;
return pass(k, 2*n+1);
}
}
Can someone give me a hint as on how to do it?
Change
n = 0;
To
return n;
To return the result.
The rest of the code is fine
Currently the behaviour of your code is undefined since you don't explicitly return a value on all control paths.
Your code can simplify down to:
int pass(int k, int n)
{
return k ? 2 * pass(k - 1, n) + 1 : 1;
}
Here I've used the ternary conditional operator. 2 * pass(k - 1, n) + 1 is returned if k is non-zero, 1 is returned otherwise.
Take care not to overflow your int in this case. Note that the maximum size of an int can be as small as 32767. Consider using a long type instead.
Also, note that recursion is not normally a good way of solving O(n) type problems; you could get errors at runtime due to a function call stack limit being exceeded: consider folding to a loop instead.
Doing an assignment on recursive functions at the moment.
Was asked to do a Fibonacci program and did so with out much issue.
But I'm need to make a counter for it, and here is where I'm getting stuck.
I've got this function
int fibonacci(int n)
{
if( n == 0 )
{
//my fibonacci code
}
else if( n == 1 )
{
//my fibonacci code
}
else
{
//my fibonacci code
}
}
So how to I add a counter to this? Ever time I add a counter it returns the wrong number.
Edit Just to clarify, my function works fine generating the Fibonacci numbers. I just wanted to add a counter inside the function so I can see how many times it is being called every time I want it to generate a Fibonacci number.
I have since tried one of the methods below where I initialise a counter in the main function then increment it in the recursion but don't know if the number is correct. For example it is saying that I'm calling the function 609 times if my Fibonacci number is 610, is that correct?
I'm guessing you just need the count for demonstration purposes, right?
Counting the calls should be easily achievable by passing in a counter variable by reference, and increasing it once at the beginning of each call, like so:
#include <iostream>
// ...
int fibonacci(int n, int &count)
{
++count;
// other code ...
// and every time you call fibonacci recursively,
// simply pass in the same reference, like so:
if (...) {
fibonacci (new_n, count);
}
}
int main(int argc, char** argv)
{
// call it with an int variable initialized to 0:
int fibCnt = 0;
fibonacci(10, fibCnt);
std::cout << "Function was called "<<fibCnt<<" times"<<std::endl;
}
You don't need any counters. Your code is already almost there
int fibonacci(int n)
{
if( n == 0 )
{
return f_0
}
else if( n == 1 )
{
return f_1
}
else
{
return f_n using recursion
}
}
As the Fibonacci numbers are defined via recursion, the last case is obvious. The other two are needed only to close the recursion relations, i.e. to avoid the last case to result in an infinite loop.
Complete the code first. I give you the recursion equations:
fib(0) = *deleted*
fib(1) = *deleted*
fib(n) = *deleted*
Your counter (which you should still specify in your question) can be usually implemented by a global variable defined outside the function but be changed within the function.
Referring to the question's edit:
Your number is not good. To not spoil your task more, I give you the answer in Erlang, so you still have some work left to figure out how to get it right in your C++ task. :-)
-module(fib).
-export([f/1]).
%% returns a tupel { fibonacci value, number function calls }
f(0) -> {0, 1};
f(1) -> {1, 1};
f(X) ->
{F1, C1} = f(X - 1), %% decompose tuple
{F2, C2} = f(X - 2),
{F1 + F2, C1 + C2}. %% return value
Running this from a shell gives:
Eshell V5.10.1 (abort with ^G)
1> c("q:/doc/erlang/fib", [{outdir, "q:/doc/erlang/"}]).
{ok,fib}
2> fib:f(0).
{0,1}
3> fib:f(1).
{1,1}
4> fib:f(2).
{1,2}
5> fib:f(3).
{2,3}
6> fib:f(4).
{3,5}
7> fib:f(5).
{5,8}
8> fib:f(6).
{8,13}
9> fib:f(7).
{13,21}
10> fib:f(15).
{610,987}
11>
Thus I get 987 function calls to get at the F(15) = 610 value.
The interesting bit here is, in the comments we talked about the proper start conditions for the Fibonacci recursion F (the situation is similar to differential equations, a different start point gets you on a different trajectory / solution).
I got it wrong with F(0) = 1 and F(1) = 1, while #WhozCraig correctly pointed out it should be F(0) = 0 and F(1) = 1.
If you look at the Erlang code above you see that the calculation of the series which yields the number of function calls is a Fibonacci type one as well (adding the last two members of the series), but that one is the one with the start values 1 and 1! :-)
Using struct could be the answer.
struct factorial
{
factorial() : counter(0)
{}
uint64_t foo(uint64_t x) {
++counter;
if(x < 2)
return 1;
else
return x * foo(x - 1);
}
template <class T>
T operator()(const T& x) {
return foo(x);
}
uint64_t counter;
} factorial;
In this case, foo is the factorial function. but doesn't have that name, because the usage of the struct will be.
// output and calls
struct factorial foo;
std::cout << foo(5) << "\n";
std::cout << foo.counter << "\n";
// output
std::cout << factorial(5) << "\n";
I learned about Horner's Rule here for the first time:
Horner's rule in C++
Since I am learning about recursion ATM, I was wondering if it is possible to implement this algorithm using recursion ?
int HornerR( int a[], int n, int x, int index )
{
if (index==n) return a[n];
else
return x*HornerR(a,n ,x,index+1) + a[index];
}
I think it's only possible with a fourth parameter.
You can do it with pointer arithmetic:
Base Case at the end of array (check n) return constant parameter
Recursive Case return current cell added to variable multiplied recursive call
Recursive Call move the array to next cell and update the counter (n)
Basically this lets you calculate the index variable by moving the array to the next position and sending that (and always using the first cell) instead of sending the whole array every time
You can implement the function as follows with 3 arguments in function, provided, the array pi contains the coefficients from highest degree to 0 from index 0 to degree+1. Ex for 3x^2 + 2x^1 + 1 => pi[3] = { 3,2,1}
int compute_by_horner(int *pi, int degree, int x)
{
int i, j;
if (degree == 0)
{
return pi[0];
}
return compute_by_horner(pi, degree-1, x) * x + pi[degree];
}
Rather than passing an index, think of a as a pointer (since it is). Along with that, you'll want to decrement n, and keep track of whether it's been reduced to zero yet, rather than keeping track of whether index==n.