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.
Related
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.
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.
What is the most elegant way to sum 'each number on odd position' with 'each number on even position multiplied by 3'? I must obide this prototype
int computeCheckSum(const int* d)
My first try was to use this but my idea was flawed. I can't find a way to tell which element is even this way.
int sum=0;
for_each(d,
d+11,
[&sum](const int& i){sum+=(i%2==1)?3*i:i;}
);
example
1 2 3 4 5
1+2*3+3+4*3+5=27
I can't find a way to tell which element is even this way.
If you insist on using for_each (there's no reason to do that here), then you track the index separately:
int computeCheckSum(const int* d, int count)
{
int sum=0;
int pos=1;
std::for_each(d, d+count,
[&sum,&pos](const int& value) { sum += pos++ % 2 ? value : value * 3; } );
return sum;
}
Note I added a count parameter, so the function can work on arrays of any length. If you're feeling really perverse, you can remove that parameter and go back to hardcoding the length so the function only works arrays with 12 elements. But if you hope to be good at this some day, doing that should make you feel gross.
These things rarely become very "elegant" in C++ (it seems C++ is asymptotically approaching Perl on the "line noise" index) but since accumulate is a left fold, you can pass the index "along the fold":
int sum = std::accumulate(d,
d + 11,
std::make_pair(0,0), // (index, result)
[](std::pair<int, int> r, int x) {
r.second += r.first % 2 ? x : 3 * x;
r.first++;
return r;
}).second;
You were right. As Mud said, it was just a terrible function design. This is what I needed.
int computeCheckSum(){
int sum = 0;
bool multiplyBy3 = false;
for (auto i : m_digits){
sum += multiplyBy3 ? 3*i : i;
multiplyBy3 = !multiplyBy3;
}
return sum;
}
Mud's solution is correct using my flawed design. A simple for loop would probably be even a better solution, as everyone said.
I am trying to understand how the following algorithms works.
#include <iostream>
using namespace std;
int maxsimum(int a[], int l, int r) {
if (l == r)
return a[l];
int m = (l+r)/2;
int u = maxsimum(a,l,m);
int v = maxsimum(a,m+1,r);
return u>v?u:v;
}
int main() {
int a[] = {34,23,45,56,30,31,57,33,55,10};
int n = sizeof(a)/sizeof(int);
cout << maxsimum(a,0,n) << endl;
return 0;
}
First, what I am interested in is that in spite of algorithm's working correctly, it is mysterious for me how it finds the maximum element. I will show how I understood this algorithm:
Step 1: we say that in case of an array, l=0 and r=10, it checks if (l>r) which does not hold of course so it calculates m=(0+10)/2;. Then do again the procedure for new bounds. The first pair is (0,5), the second is (6,10) and after the final operation it compares two returned values and finally returns the maximum element between them.
Does this algorithm always work? In each iteration it does not do any comparison, only the final step. How can it determine the maximum element at each recursive iteration? It checks only what. For example: take pair(0,5), is (0 more than 5)? No, so repeat again and divide these bounds into two so get new average value m1=(0+5)/2 then again again and return some element but not the maximum. Also for second subarray we can say the same.
What is the main idea of this algorithm?
Your confusion is understandable: the algorithm as written contains a couple of bugs. It accesses memory past the end of a, which is very, very bad. Also, the test whether a range contains only one element is incorrect. If not addressed, this leads to a stack overflow.
The way the maximum function is called suggests that the lower bound is included in the range, but the upper bound is not. a[0] is valid, but a[n] accesses memory past the end of a. When splitting the range, we want the first part to run from l up to but not including m, and the second part to start at m and run up to but not include r. In other words: the "exclusive" upper limit of the first part is equal to the "inclusive" lower limit of the second part. The first internal call to maxsimum is correct. The second internal call should be:
int v=maxsimum(a,m,r);
This leaves us with the problem of detecting a range of length 1. As it stands, the algorithm actually looks for an empty range. The proper test is to look at the difference between the upper and the lower bound:
if (r-l == 1) return a[l];
The complete function is as follows:
int maxsimum(int a[],int l,int r){
if (r-l==1) return a[l];
int m=(l+r)/2;
int u=maxsimum(a,l,m);
int v=maxsimum(a,m,r);
return u>v?u:v;
}
Now that we have a correct program, the explanation of how this works is straightforward:
If the range contains only one element, then this element is the maximum.
If the range contains more than one element, we split it in two parts. We call the function recursively to compute the maximum of each part. The maximum of these two values is the maximum of the entire range.
The main idea is that if we divide the array in 2 subarrays, then the maximum must be in the left or in the right part of the array; there's no other possibility.
So we find the maximum in the left part, we find the maximum in the right part and the global maximum will obviously be the maximum between the two maximum, that is what is returned by the last line of the maxsimum function.
Your error is here:
In each iteration it does not do any comparison, only the final step.
This is wrong. In fact, it does a comparison in every step of the recursion (except in the base cases, i.e. where the array size is 1).
Let me comment the maximum part of the code for you, and try not to add confusion:
if (l==r) return a[l]; //trivial case, if there is only one value in the array return it
int m=(l+r)/2; //find value halfway into the array
int u=maxsimum(a,l,m); //find the maximum value for the lower part of the array
int v=maxsimum(a,m+1,r); //find the maximum value for the top part of the array
return u>v?u:v; //return the highest value of them.
So the array 0..10 is splitted into 0..5 and 6..10 and passed into the same function. Only when there is only one value the recursion ends and that single value is passed to their callees. Then in the second lowest cases, like value a[0] and a[1] it will do the first comparisons. The results of these will be passed up to the higher cases until it will exit the function for the final time returning with the largest value of all the cases.
I hope was able clarify a bit for you.
Error in main() function, test array has 10 elements, should be:
cout << maxsimum(a,0,n-1) << endl;
This answer might be so late, but it may be useful to someone to grasp the recursion calls, I modified the above code to trace out the function calls.
After seeing the output it is easy to see how a recursive tree is made.
#include <iostream>
using namespace std;
int maxsimum(int a[], int l, int r) {
if (l == r)
return a[l];
int m = (l+r)/2;
cout<<"values gonna get computed in 1st recursive call"<< l<<" "<< m<<"\n";
int u = maxsimum(a,l,m);
cout<<"value of u "<<u<<"\n";
cout<<"value gonna get computed in 2nd recursion call "<<m+1 <<" "<<r<<"\n";
int v = maxsimum(a,m+1,r);
cout<<"value of v : "<<v<<"\n";
cout<<"current u value :"<<u <<"current v value "<<v <<"\n";
return u>v?u:v;
}
int main() {
int a[] = {5,6,7,8,9};
int n = sizeof(a)/sizeof(int);
cout << maxsimum(a,0,n-1) << endl;
return 0;
}
Here is the recursion tree for the above program, the tree first goes towards the left side i.e for the first recursive statement, then each call returns its base value, the return condition makes sure only the maximum element is selected in each calls.
(9)
(0,4)
/ \
7 / \9
(0,2) (3,4)
/ \ / \
6/ \7 8/ \9
(0,1) (2,2) (3,3) (4,4)
/ \
5/ \6
(0,0) (1,1)