Reset a counter in recursive methods - java

I am trying to write a recursive method which gives me the biggest-sum-pairs of integer (neighbors) within an array. It works perfectly, but only for the first run, because i cannot reset my static int maxSum; "counter" which I use to check, if the current sum is bigger than the biggest sum of previous runs. maybe you can give me an hint, its the first time I work with static counters in a recursion
static int maxSum = 0;
private static int getMaxPairSum(int[] workArray, int start, int end) {
while(start < end){
if (workArray[start] + workArray[start+1] > maxSum){
maxSum = workArray[start] + workArray[start+1];
return getMaxPairSum(workArray,start +1,end);
}
else return getMaxPairSum(workArray,start +1,end);
}
return maxSum;
}

A very simple way to do this could be:
Creating a temporary variable
Assigning the value of maxSum to the variable
Resetting maxSum
Returning the temporary variable
Would be like this:
while(start < end){
if (workArray[start] + workArray[start+1] > maxSum){
maxSum = workArray[start] + workArray[start+1];
return getMaxPairSum(workArray,start +1,end);
}
else return getMaxPairSum(workArray,start +1,end);
}
int tempMaxSum = maxSum;
maxSum = 0;
return tempMaxSum;
Hope this helped!

Thank you for your help! I decided to write a new code, it works perfectly and is recursive :D
private static int getMaxPairSum(int[] workArray, int start, int end) {
if (start==end)
return 0;
return Math.max((workArray[start] + workArray[start+1]), getMaxPairSum(workArray,start+1,end));

I feel like you’re still thinking too much in an iterative programming mindset. In recursion, you shouldn’t really need a global variable to keep track of changes. Instead, the changes should instead propagate either up (still very iterative thinking) or down (proper recursion!) your recursion stack, with the operation (in this case a comparison) being performed at each function call in that stack.
It should be the case that transitivity of the greater than operator applies here, so the max will be the largest regardless of when in the list it happens, so it doesn’t really matter when we find it. Try to come up with some concrete examples and walk through a few iterations of your method if that seems unclear.
An example of it being passed up your recursion stack would be adding a new argument to your method, such as “maxSum” and passing that through to each call, keeping track of the max at each call. Returning from this would still feel a bit "off", though, as you'd have the value of your result once you reach the end of the list, but then would still need to return it through all the recursive calls you made to the method until it got back to the first call.
The “most recursive” approach, here, would be to let your method work with a value that hasn't been determined yet but that it knows will be determined in the future, and to do that until it reaches the end case. Once it reaches the end, it will have gotten a concrete value, which allows an undetermined value for the previous call to now be determined, which allows an undetermined value for the call before that to be determined, etc., until the first call.
Here, the comparison would be Math.max(currentSum, nextSum), where currentSum = workArray[i] + workArray[i+1] and nextSum is the value returned by the next call to getMaxPairSum, which won’t actually be determined until you get to the end of the array (your terminating case for the recursion) which will return a value to the call before it, which in returns a value to the call before it, which returns a value to the call before it, and so on until you get back to the first call and so have your final value.
For a visualization based in data structures, this means that the calculations will propagate down the recursive function call stack until the very first call, which is the bottommost item in the stack.

Related

How to find out where arguments come from to the specific parameter in Java?

I've come to wonder if there is a way to find out which method arguments are returned from.
If you have a few methods in a few classes, perhaps it's easier to figure out where the values come from to the parameter by looking at the method signature.
What if we have very complicated structure of classes? how can we efficiently figure it out? (other than using debugger)
I would appreciate your advice!
For example,
public class Recursion_fig18_9 {
//recursive declaration of method factorial
public static long factorial(long number){
long result = 1;
//iterative declaration of method factorial
for (long i = number; i >=1; i--){
result *= i;
}
return result;
}
//output factorials for values of 0 to 10
public static void main(String[] args) {
//calculate the factorials from 0 to 10
for (int counter =0; counter <= 10; counter ++){
System.out.printf("%d! = %d%n", counter, factorial(counter));
}
}
(Although this example is quite small structure of class,)
How can I figure out where "number" is returned from in the factorial method?
Using your debugger you can set a break point within the method. When that method breaks, you'll see a stack frame indicating where the call to the method came from and this will help you to trace back the method call to figure out how it was constructed.
Within your code example, place the breakpoint on the return statement so that you can examine the return value before it is returned.
Alternatively, you could use a logger to generate a log file and see how your code steps through it. You'd be able to back off the logging level after the fact so that you don't have to change code constantly. More on logging here
I am looking back at my old question and I am answering to my own question.
You can figure out easily without using debug which method calls the current method and passes the parameters by
selecting the current method
right mouse click
click Open Call Hierarchy (or Ctrl + Alt + H).

Recursive binary search -- Java

I've searched extensively online but all solutions I've found use two parameters to keep track of the size of the area being used. This would be easy if I was allowed to do that, but I'm not. As you can see below, the code lacks a stop value, because I have no idea how to retain the original information.
This is the code on Wikipedia, you can see they use imin and imax for tracker variables: http://en.wikipedia.org/wiki/Binary_search_algorithm#Recursive
My (very incorrect) code is below. The mid variable doesn't mean anything, because I don't know how to set low and high correctly if I'm not allowed to have any extra arguments in the function.
public static int findRecursiveB( String s, char c)
{
int low = 0;
int high = s.length()-1;
int mid = (low+high)/2;
if (s.charAt(mid) < c) {
return findRecursiveB(s.substring(low, mid), c);
}
else if (s.charAt(mid) >= c) {
return findRecursiveB(s.substring(mid+1, high), c);
}
else return mid;
}
One crucial point here is what does the original String s contain? For this to work, it has to be a sorted String, meaning that the characters in the String must be in order. Specifically, it looks like you've written code that expects s to be sorted in reverse order. Otherwise, unless I'm totally missing something, your code does exactly what it is supposed to: no need to pass extra params because you are passing in the substring on each recursive call.
Otherwise, good job.

Understanding basic recursion function in Java to calculate positive integers in array

I am trying to learn recursion in Java and have an array that takes in continuous input until the Scanner reads in a 0.
From there I have a method that (attempts) to calculate the number of positive integers in the array using recursion. This is the first recursive function I have ever written and I keep getting a stackoverflow error.
I have read tutorials and I still can't wrap my head around the basic understanding of recursion.
public class reuncF {
private static int start = 0;
private static int end = 98;
public static void main(String[] args) {
input = input.nextDouble();
list[i] = numInput;
computeSumPositive(numList, count);
}
}
return positives += solve(numbers, count++);
}
}
You forgot to stop your recursion!
There has to be some case where computeSumPositive returns without calling itself again. Otherwise it'll just keep going forever, never getting back to you.
If you did it with a loop, the loop would look like this:
int positives = 0;
for (int i = 0; i < numList.length; ++i) {
if (numList[i] > 0) {
positives++;
}
}
To do that recursively, you just find out what are the variables used in the loop. They are i, numList and positives.
computeSumPositive(int i, double[] numList, int positives)
Then we take a look at what the loop does. First, it checks whether we went too far,
so our recursive function should do that too. It'll have to return instead of just falling through like the loop does. And obviously, it must return the result:
{
if (! (i < numList.length))
return positives;
The loop then does the test and maybe increments positives, so the recursive function should also do that:
if (numList[i] > 0) {
positives++;
}
At the end of the loop, i is updated:
i++;
The loop just starts over, but the recursive function will have to call itself. Of course, we want it to use the new value of i and positives, but fortunately we updated those, so now we can just do:
return computeSumPositives (i, numList, positives);
}
The tricky bit is that the values i, numList, and are local to each call. Each invocation of computeSumPositives can see only the arguments it were given. If it changes them, none of the other invocation can see that change.
EDIT: So if we, for reasons we can only speculate about, wanted desperately for computeSumPositive to take only 2 parameters, we would have to "split up" positives across each invocation. Each invocation knows whether or not its number was positive or not; all we have to do is add them. Then it looks like this:
computeSumPositive(int i, double[] numList)
{
if (! (i < numList.length))
return 0; // I didn't find any at index i
if (numList[i] > 0) {
// Theres one I found + however many my later
// invocations will find.
return 1 + computeSumPositive (i+1, numList);
} else {
// I didn't find any, but my later invocations might.
return computeSumPositive (i+1, numList);
}
}
I find it helpful, when dealing with recursion, to figure out the termination case first.
It looks like you are treating 'count' as an index. So you could check if your at the last index in the array, if so and if the value is positive return a 1, if the value is non-positive return a 0 - dont recurse anymore.
If your not at the last index, and the value is positive return a 1 + the recursive function call, or if the value is non-positive just continue to recurse.
This will still cause a stack overflow for large arrays.
The value of count++ is the same as the value of count; the program uses the value and then increments it. But the result is that computeSumPositive keeps calling itself with the same value of count, which leads to infinite recursion. Note that each time computeSumPositive calls another computeSumPositive, each call has its own copy of the parameters (like count) and the local variables; so incrementing one computeSumPositive's copy of count has no effect on the value of count used by other recursive calls.
Change count++ to count + 1, and also add a way to halt the recursion. (At some point, you will be calling computeSumPositive to look at zero integers, and at that point, it should just return 0 and not call itself. You need to think about: how do you test whether you've reached that point?)

Is this a proper use of recursion?

I made what I think is an example of recursion. Is this acceptable? It's not for a project or anything, my professor is just awful so I try to teach myself.
public void theCat() {
int i;
for (i = 0; i <= 50; i++) {
System.out.println(i);
if (i == 10) {
theCat();
}
}
}
Yes, that is recursion. However, it will be infinite since you never stop it.
What you should do is to have a base case where you check if it is time to stop the recursion. You would also have a reduction step, that will converge the parameter towards the base case, like so:
public int theCat(int i) {
if (i => 50)
return i;
else
return theCat(i + 1);
}
To show the effectiveness of this, have a look at a recursive factorial method:
private long factorial(int n) {
if (n == 1)
return 1;
else
return n * factorial(n-1);
}
Here, the base case checks if we are trying to calculate 1! and in that case returns 1. This is the case where we no longer need to recursively call the method. Instead, we walk backwards along all of the method calls we have made to calculate the final answer:
factorial(5)
factorial(4)
factorial(3)
factorial(2)
factorial(1)
return 1
return 2*1 = 2
return 3*2 = 6
return 4*6 = 24
return 5*24 = 120
This will cause overflow. All recursion should have some kind of base case for exiting so that it does not go infinitely.
Additionally all recursive functions usually receive some kind of an int or some value so that they can use that value in the base case and exit. So for your example I would send int i as an argument into cat and stop when i == 50
Yes and no. Technically this is an example of recursion. But this will never terminate. Normally there is some parameter passed into a recursive method so that it can recognize a "base case" which will not recurse.
Yes, but you must have flag that determine exit from your method, otherwise you catch StackOverFlowError
That will cause a stack overflow as the recursive call is infinite.
We can define recursion in this way:
1. we start with a method that has a specific state
2. inside this method the method itself is called, but the call changes the state of the method
3. the method has a base case (a case where if a method reaches this state it no longer calls itself recursively).

How to detect an infinite loop in a recursive call?

I have a function that is recursively calling itself, and i want to detect and terminate if goes into an infinite loop, i.e - getting called for the same problem again. What is the easiest way to do that?
EDIT: This is the function, and it will get called recursively with different values of x and y. i want to terminate if in a recursive call, the value of the pair (x,y) is repeated.
int fromPos(int [] arr, int x, int y)
One way is to pass a depth variable from one call to the next, incrementing it each time your function calls itself. Check that depth doesn't grow larger than some particular threshold. Example:
int fromPos(int [] arr, int x, int y)
{
return fromPos(arr, x, y, 0);
}
int fromPos(int [] arr, int x, int y, int depth)
{
assert(depth < 10000);
// Do stuff
if (condition)
return fromPos(arr, x+1, y+1, depth + 1);
else
return 0;
}
If the function is purely functional, i.e. it has no state or side effects, then you could keep a Set of the arguments (edit: seeing your edit, you would keep a Set of pairs of (x,y) ) that it has been called with, and every time just check if the current argument is in the set. That way, you can detect a cycle if you run into it pretty quickly. But if the argument space is big and it takes a long time to get to a repeat, you may run out of your memory before you detect a cycle. In general, of course, you can't do it because this is the halting problem.
You will need to find a work-around, because as you've asked it, there is no general solution. See the Halting problem for more info.
An easy way would be to implement one of the following:
Pass the previous value and the new value to the recursive call and make your first step a check to see if they're the same - this is possibly your recursive case.
Pass a variable to indicate the number of times the function has been called, and arbitrarily limit the number of times it can be called.
You can only detect the most trivial ones using program analysis. The best you can do is to add guards in your particular circumstance and pass a depth level context. It is nearly impossible to detect the general case and differentiate legitimate use of recursive algorithms.
You can either use overloading for a consistent signature (this is the better method), or you can use a static variable:
int someFunc(int foo)
{
static recursionDepth = 0;
recursionDepth++;
if (recursionDepth > 10000)
{
recurisonDepth = 0;
return -1;
}
if (foo < 1000)
someFunc(foo + 3);
recursionDepth = 0;
return foo;
}
John Kugelman's answer with overloading is better beacuse it's thread safe, while static variables are not.
Billy3
Looks like you might be working on a 2D array. If you've got an extra bit to spare in the values of the array, you can use it as a flag. Check it, and terminate the recursion if the flag has been set. Then set it before continuing on.
If you don't have a bit to spare in the values, you can always make it an array of objects instead.
If you want to keep your method signature, you could keep a couple of sets to record old values of x and y.
static Set<Integer> xs;
static Set<Integer> ys;//Initialize this!
static int n=0;//keeps the count function calls.
int fromPos(int [] arr, int x, int y){
int newX= getX(x);
int newY= getY(y);
n++;
if ((!xs.add(Integer.valueOf(newX)) && !ys.add(Integer.valueOf(newY))){
assert(n<threshold); //threshold defined elsewhere.
fromPos(arr,newx,newy);
}
}
IMHO Only loops can go into an infinite loop.
If your method has too many level of recursion the JVM will throw a StackOverflowError. You can trap this error with a try/catch block and do whatever you plan to do when this condition occurs.
A recursive function terminates in case a condition is fulfilled.
Examples:
The result of a function is 0 or is 1
The maximum number of calls is reached
The result is lower/greater than the input value
In your case the condition is ([x0,y0] == [xN,yN]) OR ([x1,y1] == [xN,yN]) OR ([xN-1,yN-1] == [xN,yN])
0, 1, ...N are the indexes of the pairs
Thus you need a container(vector, list, map) to store all previous pairs and compare them to the current pair.
First use mvn findbugs:gui to open a gui which point to the line where this error is present.
I also faced the same problem and I solved it by adding a boolean variable in the loop verification.
Code before ->
for (local = 0; local < heightOfDiv; local = local + 200) { // Line under Error
tileInfo = appender.append(tileInfo).append(local).toString();
while (true) {
try {
tileInfo = appender.append(tileInfo).append(getTheTextOfTheElement(getTheXpathOfTile(incr))).toString();
incr++;
} catch (Exception e) {
incr = 1;
tileInfo = appender.append(tileInfo).append("/n").toString();
}
}
To Solve this problem, I just added a boolean variable and set it to false in the catch block. Check it down
for (local = 0; local < heightOfDiv; local = local + 200) {
tileInfo = appender.append(tileInfo).append(local).toString();
boolean terminationStatus = true;
while (terminationStatus) {
try {
tileInfo = appender.append(tileInfo).append(getTheTextOfTheElement(getTheXpathOfTile(incr))).toString();
incr++;
} catch (Exception e) {
incr = 1;
tileInfo = appender.append(tileInfo).append("/n").toString();
terminationStatus = false;
}
}
This is how i Solved this problem.
Hope this will help. :)

Categories