How can I "unroll" this sigma notation as a recursive method - java

In my java programming class, we have a lab assignment (not worth points) to implement several recursive methods. I have completed the recursive method based on a given recursive function, and I have completed a necessary factorial recursive method for the remaining portion, which is a sigma series that I am currently having a hard time wrapping my head around.
We are given this formula:
s(n) = sigma[(s(n - i) - 1) / i!, i = 1, n] and s(0) = 0
and I have written out the results for s(1)-s(5) (using my graphing calculator to verify my answers as I go), but I am having difficulty figuring out how to correctly implement this recursive process.
I have built a "sigma" method that works appropriately to the best of my knowledge, and so I think I have issues with my "formula" method. Worst of all, the formula looks right (to the best of my thinking) and the code is currently getting stuck in an infinite loop.
// ... Rest of code omitted for brevity
private static double sequence2(int i) {
if (i <= 0) { return 0; }
return (sequence2(max - i) - 1) / factorial(i); // max is defined in other code
}
private static double sigma(int n) {
if (n <= 0) { return 0; }
return sequence2(n) + sigma(n - 1);
}
private static int factorial(int n) {
if (n <= 1) { return 1; }
return n * factorial(n - 1);
}
Where should I begin for figuring out how to correctly unroll this recursive sequence?

According to the formula you've linked the recursion should be(changing the name of the variables to correlate) :
private static double sequence2(int n) {
if (n == 0) { return 0; }
return (sequence2(n-1) - 1) / factorial(n-1);
}
this shall generate the sequence in the reverse order from S(n-1), S(n-2) ... S(1)

After talking to my teacher, he provided the following method as an acceptable way to calculate the correct values:
static double generateSigmaSequnce(int n) {
if (n < 1) { return 0; }
double sum = 0;
for (int i = 1; i <= n; i++) {
sum += (generateSigmaSequnce(n - i) - 1) / factorial(i);
}
return sum;
This code does indeed return the correct values for the sigma sequence, but to my mind it is somewhat unsatisfactory as we've had to use an iterative loop to drive behavior in an exercise in recursion. I will be puzzling out from here to determine if I can create a new method/augment this method to include a recursive summation, but for the time being (and in my teacher's own code) this is correct.

Related

Implementing N choose K recursively in Java

I am new to Java and am I trying to implement a recursive method for finding "n choose k".
However, I've run into a problem.
public class App {
public static void main(String[] args) throws Exception {
int n = 3;
int k = 2;
int result = combRecursion(n, k);
System.out.println(result);
}
private static int combRecursion(int n, int k) {
if (k == 0) {
return 1;
} else {
return (combRecursion(n - 1, k - 1) + combRecursion(n - 1, k));
}
}
Output:
many repetitions of this line:
at App.combRecursion(App.java:14)
It's possible to pick k items from the set of n items only if n is greater or equal to k.
You need to cut off fruitless branches of recursion spawn by the call combRecursion(n - 1, k) which doesn't reduce the number of item in the sample.
When you need to create a recursive method, it should always contain two parts:
Base case - that represents a set of edge-cases, trivial scenarios for which the result is known in advance. If the recursive method hits the base case (parameters passed to the method match one of the conditions of the base case), recursion terminates. In for this task, the base case will represent a situation when the source list was discovered completely and position is equal to its size (invalid index).
Recursive case - a part of a solution where recursive calls are made and where the main logic resides.
Your recursive case is correct: it spawns two recursive branches of execution (one will "pick" the current item, the second will "reject" it).
But in the base case, you've missed the scenario mentioned above, we need to address these situations:
n isn't large enough (k > n), so that is not possible to fetch k item. And the return value will be 0 (or instead of returning a value, you might throw an exception).
k == 0 result should be 1 (it's always possible to take 0 items, and there's only one way to do it - don't pick anything).
When k == n - there's only one way to construct a combination, as #akuzminykh has pointed out. And the return value will be 1
Note that because your goal is to get familiar with the recursion (I'm pretty sure that you're doing it as an exercise) there's no need to mimic the mathematical formula in your solution, use pure logic.
Here is how you can implement it:
private static int combRecursion(int n, int k) {
if (k > n) return 0; // base case - impossible to construct a combination
if (n == k || k == 0) return 1; // base case - a combination was found
// recursive case
return combRecursion(n - 1, k - 1) + combRecursion(n - 1, k);
}
main() - demo
public static void main(String[] args) {
System.out.println(combRecursion(3, 2));
System.out.println(combRecursion(5, 2));
}
Output
3 // pick 2 item from the set of 3 items
10 // pick 2 item from the set of 5 items
Your base case ought to include both n == k || k == 0 for "n choose k" to be implemented correctly. That way, both calls will eventually terminate (even though your current implementation is rather inefficient as it has exponential runtime). A better implementation would use the formula n!/k!/(n-k)! or the multiplicative formula to run in linear time:
int factorial(int n) {
int res = 1;
for (; n > 1; n--) {
res *= n;
}
return res
}
int choose(int n, int k) {
return factorial(n)/factorial(k)/factorial(n-k);
}
further optimizing this is left as an exercise to the reader (hint: a single for loop suffices).

Stack Overflow Error when trying to create an exponent calculator using recursion in java

I'm trying to make a simple calculator to practice recursion. This is my code and I'm getting a stack overflow error. I don't necessarily care about the code to make this work as I want to figure it out myself, but I'm not sure why I would get a stack over flow error for this.
Declared in my main:
int base=3,exponent=4;
My exponent method:
static int powerN(int base, int n)
{
if ( n == 0 ) return 0;
return base * powerN (1, n-(n-1));
}
You have at least three bugs I can see. x0 is one (not zero). You should handle the case of x1 (which is x). And, when you recurse you want to pass base and n - 1 (as is you are recursing on a power of 1 - which will always be one). Like,
static int powerN(int base, int n) {
if (n == 0) {
return 1;
} else if (n == 1) {
return base;
}
return base * powerN(base, n - 1);
}

I want to solve Project Euler #1 more efficiently by using arithmetic progression formula, but my algorithm returns answers that are just slightly off

This is the first, inefficient method I wrote:
public int sumOfMultiplesOf3or5Under1000() {
int sum = 0;
for (int i = 0; i < 1000; i++) {
if (i % 3 == 0 || i % 5 == 0) {
sum += i;
}
}
return sum;
}
Here is my attempt at coding a more efficient solution using the arithemtic progression formula:
public int usingAP() {
return sumOfAP(3,3,333) + sumOfAP(5,5,199) - sumOfAP(15,15,66);
}
public int sumOfAP(int firstTerm, int commonDifference, int numberOfTerms){
int sum = (numberOfTerms / 2) * (2 * firstTerm + (numberOfTerms -
1) * commonDifference);
return sum;
}
When I call sumOfMultiplesOf3or5Under1000() I get the correct answer:
233168
When I call usingAP() I get an answer that's off by just 1,001:
232167
I'm not sure why you consider your first method to be inefficient for the reason that I stated in the comment above. Nevertheless, it seems you fell victim to rounding errors in your sumOfAP method. You were close, but you just need some way to store the temporary variables as double instead of int so you can retain the precision. I was able to fix it by dividing and multiplying by 2D instead of 2:
public static int sumOfAP(int firstTerm, int commonDifference, int numberOfTerms){
return (int) ((numberOfTerms / 2D) * (2D * firstTerm + (numberOfTerms - 1) * commonDifference));
}
You can run the following and verify that they're equivalent:
System.out.println(usingAP());
System.out.println(sumOfMultiplesOf3or5Under1000());
Output:
233168
233168

Recursively finding the average of even numbers in an array

I'm trying to find the average of all even numbers in an array using recursion and I'm stuck.
I realize that n will have to be decremented for each odd number so I divide by the correct value, but I can't wrap my mind around how to do so with recursion.
I don't understand how to keep track of n as I go, considering it will just revert when I return.
Is there a way I'm missing to keep track of n, or am I looking at this the wrong way entirely?
EDIT: I should have specified, I need to use recursion specifically. It's an assignment.
public static int getEvenAverage(int[] A, int i, int n)
{
// first element
if (i == 0)
if (A[i] % 2 == 0)
return A[0];
else
return 0;
// last element
if (i == n - 1)
{
if (A[i] % 2 == 0)
return (A[i] + getEvenAverage(A, i - 1, n)) / n;
else
return (0 + getEvenAverage(A, i - 1, n)) / n;
}
if (A[i] % 2 == 0)
return A[i] + getEvenAverage(A, i - 1, n);
else
return 0 + getEvenAverage(A, i - 1, n);
}
In order to keep track of the number of even numbers you have encountered so far, just pass an extra parameter.
Moreover, you can also pass an extra parameter for the sum of even numbers and when you hit the base case you can return the average, that is, sum of even numbers divided by their count.
One more thing, your code has two base cases for the first as well as last element which is unneeded.
You can either go decrementing n ( start from size of array and go till the first element ), or
You can go incrementing i starting from 0 till you reach size of array, that is, n.
Here, is something I tried.
public static int getEvenAvg(int[] a, int n, int ct, int sum) {
if (n == -1) {
//make sure you handle the case
//when count of even numbers is zero
//otherwise you'll get Runtime Error.
return sum/ct;
}
if (a[n]%2 == 0) {
ct++;
sum+=a[n];
}
return getEvenAvg(a, n - 1, ct, sum);
}
You can call the function like this getEvenAvg(a, size_of_array - 1, 0, 0);
Example
When dealing with recursive operations, it's often useful to start with the terminating conditions. So what are our terminating conditions here?
There are no more elements to process:
if (index >= a.length) {
// To avoid divide-by-zero
return count == 0 ? 0 : sum / count;
}
... okay, now how do we reduce the number of elements to process? We should probably increment index?
index++;
... oh, but only when going to the next level:
getEvenAverage(elements, index++, sum, count);
Well, we're also going to have to add to sum and count, right?
sum += a[index];
count++;
.... except, only if the element is even:
if (a[index] % 2 == 0) {
sum += a[index];
count++;
}
... and that's about it:
static int getEvenAverage(int[] elements, int index, int sum, int count) {
if (index >= a.length) {
// To avoid divide-by-zero
return count == 0 ? 0 : sum / count;
}
if (a[index] % 2 == 0) {
sum += a[index];
count++;
}
return getEvenAverage(elements, index + 1, sum, count);
}
... although you likely want a wrapper function to make calling it prettier:
static int getEvenAverage(int[] elements) {
return getEvenAverage(elements, 0, 0, 0);
}
Java is not a good language for this kind of thing but here we go:
public class EvenAverageCalculation {
public static void main(String[] args) {
int[] array = {1,2,3,4,5,6,7,8,9,10};
System.out.println(getEvenAverage(array));
}
public static double getEvenAverage(int[] values) {
return getEvenAverage(values, 0, 0);
}
private static double getEvenAverage(int[] values, double currentAverage, int nrEvenValues) {
if (values.length == 0) {
return currentAverage;
}
int head = values[0];
int[] tail = new int[values.length - 1];
System.arraycopy(values, 1, tail, 0, tail.length);
if (head % 2 != 0) {
return getEvenAverage(tail, currentAverage, nrEvenValues);
}
double newAverage = currentAverage * nrEvenValues + head;
nrEvenValues++;
newAverage = newAverage / nrEvenValues;
return getEvenAverage(tail, newAverage, nrEvenValues);
}
}
You pass the current average and the number of even elements so far to each the recursive call. The new average is calculated by multiplying the average again with the number of elements so far, add the new single value and divide it by the new number of elements before passing it to the next recursive call.
The way of recreating new arrays for each recursive call is the part that is not that good with Java. There are other languages that have syntax for splitting head and tail of an array which comes with a much smaller memory footprint as well (each recursive call leads to the creation of a new int-array with n-1 elements). But the way I implemented that is the classical way of functional programming (at least how I learned it in 1994 when I had similar assignments with the programming language Gofer ;-)
Explanation
The difficulties here are that you need to memorize two values:
the amount of even numbers and
the total value accumulated by the even numbers.
And you need to return a final value for an average.
This means that you need to memorize three values at once while only being able to return one element.
Outline
For a clean design you need some kind of container that holds those intermediate results, for example a class like this:
public class Results {
public int totalValueOfEvens;
public int amountOfEvens;
public double getAverage() {
return totalValueOfEvens + 0.0 / amountOfEvens;
}
}
Of course you could also use something like an int[] with two entries.
After that the recursion is very simple. You just need to recursively traverse the array, like:
public void method(int[] values, int index) {
// Abort if last element
if (index == values.length - 1) {
return;
}
method(array, index + 1);
}
And while doing so, update the container with the current values.
Collecting backwards
When collecting backwards you need to store all information in the return value.
As you have multiple things to remember, you should use a container as return type (Results or a 2-entry int[]). Then simply traverse to the end, collect and return.
Here is how it could look like:
public static Results getEvenAverage(int[] values, int curIndex) {
// Traverse to the end
if (curIndex != values.length - 1) {
results = getEvenAverage(values, curIndex + 1);
}
// Update container
int myValue = values[curIndex];
// Whether this element contributes
if (myValue % 2 == 0) {
// Update the result container
results.totalValueOfEvens += myValue;
results.amountOfEvens++;
}
// Return accumulated results
return results;
}
Collecting forwards
The advantage of this method is that the caller does not need to call results.getAverage() by himself. You store the information in the parameters and thus be able to freely choose the return type.
We get our current value and update the container. Then we call the next element and pass him the current container.
After the last element was called, the information saved in the container is final. We now simply need to end the recursion and return to the first element. When again visiting the first element, it will compute the final output based on the information in the container and return.
public static double getEvenAverage(int[] values, int curIndex, Results results) {
// First element in recursion
if (curIndex == 0) {
// Setup the result container
results = new Results();
}
int myValue = values[curIndex];
// Whether this element contributes
if (myValue % 2 == 0) {
// Update the result container
results.totalValueOfEvens += myValue;
results.amountOfEvens++;
}
int returnValue = 0;
// Not the last element in recursion
if (curIndex != values.length - 1) {
getEvenAverage(values, curIndex + 1, results);
}
// Return current intermediate average,
// which is the correct result if current element
// is the first of the recursion
return results.getAverage();
}
Usage by end-user
The backward method is used like:
Results results = getEvenAverage(values, 0);
double average results.getAverage();
Whereas the forward method is used like:
double average = getEvenAverage(values, 0, null);
Of course you can hide that from the user using a helper method:
public double computeEvenAverageBackward(int[] values) {
return getEvenAverage(values, 0).getAverage();
}
public double computeEvenAverageForward(int[] values) {
return getEvenAverage(values, 0, null);
}
Then, for the end-user, it is just this call:
double average = computeEvenAverageBackward(values);
Here's another variant, which uses a (moderately) well known recurrence relationship for averages:
avg0 = 0
avgn = avgn-1 + (xn - avgn-1) / n
where avgn refers to the average of n observations, and xn is the nth observation.
This leads to:
/*
* a is the array of values to process
* i is the current index under consideration
* n is a counter which is incremented only if the current value gets used
* avg is the running average
*/
private static double getEvenAverage(int[] a, int i, int n, double avg) {
if (i >= a.length) {
return avg;
}
if (a[i] % 2 == 0) { // only do updates for even values
avg += (a[i] - avg) / n; // calculate delta and update the average
n += 1;
}
return getEvenAverage(a, i + 1, n, avg);
}
which can be invoked using the following front-end method to protect users from needing to know about the parameter initialization:
public static double getEvenAverage(int[] a) {
return getEvenAverage(a, 0, 1, 0.0);
}
And now for a completely different approach.
This one draws on the fact that if you have two averages, avg1 based on n1 observations and avg2 based on n2 observations, you can combine them to produce a pooled average:
avgpooled = (n1 * avg1 + n2 * avg2) / (n1 + n2).
The only issue here is that the recursive function should return two values, the average and the number of observations on which that average is based. In many other languages, that's not a problem. In Java, it requires some hackery in the form of a trivial, albeit slightly annoying, helper class:
// private helper class because Java doesn't allow multiple returns
private static class Pair {
public double avg;
public int n;
public Pair(double avg, int n) {
super();
this.avg = avg;
this.n = n;
}
}
Applying a divide and conquer strategy yields the following recursion:
private static Pair getEvenAverage(int[] a, int first, int last) {
if (first == last) {
if (a[first] % 2 == 0) {
return new Pair(a[first], 1);
}
} else {
int mid = (first + last) / 2;
Pair p1 = getEvenAverage(a, first, mid);
Pair p2 = getEvenAverage(a, mid + 1, last);
int total = p1.n + p2.n;
if (total > 0) {
return new Pair((p1.n * p1.avg + p2.n * p2.avg) / total, total);
}
}
return new Pair(0.0, 0);
}
We can deal with empty arrays, protect the end-user from having to know about the book-keeping arguments, and return just the average by using the following public front-end:
public static double getEvenAverage(int[] a) {
return a.length > 0 ? getEvenAverage(a, 0, a.length - 1).avg : 0.0;
}
This solution has the benefit of O(log n) stack growth for an array of n items, versus O(n) for the various other solutions that have been proposed. As a result, it can deal with much larger arrays without fear of a stack overflow.

Find the value of pi from the infinite series (pi=4-4/3+4/5-4/7+4/9-4/11…. ) using recursion in java

I have written multiple attempts to this problem, but I think this is the closest I could get. This solution makes the method recurse infinitely, because I don't have a base case, and I can't figure it out. The counter++ line is unreachable, and I can't get this to work, and I am very tired. This would be very easy with a loop, but recursion is kind of a new concept to me, and I would be thankful if someone helped me solve this.
public static double pi(int a, double b){
int counter=0;
if (counter %2==0){
return a-(a/(pi(a,b+2)));
counter++;
} else {
return a+(a/(pi(a,b+2)));
counter++;
}
You could pass in another int, say limit, and add this code:
if (b > limit) {
return a;
}
Or you could pass in some tolerance value:
if (pi(a,b+2) < tolerance) {
return a;
}
Whenever you're working with recursion it's good to establish an exit strategy up front.
Here is an implementation that works. Do not use it:
public static double term(double acc, int n, int r) {
if (r-- > 0) {
double sgn = (n % 4 == 1) ? +1.0 : -1.0;
acc += sgn * 4.0 / n;
n += 2;
return term(acc, n, r);
} else {
return acc;
}
}
public static double pi() {
return term(0.0, 1, 1000);
}
The reason not to use it is that this particular infinite series is a particularly poor way of calculating π because it converges very slowly. In the example above event after 1000 iterations are performed it's still only correct to 3 decimal places because the final calculated term is 4 / 1000.
Going much beyond 1000 iterations results in a stack overflow error with little improvement in the accuracy even though the term function is (I think) potentially tail recursive.

Categories

Resources