unwind to the first frame of a recursive call in Java? - java

Suppose I have a (very simple) recursive method like this:
public static void myMeth(int n)
{
// do something
// now execute the recursive call
if (n < 0) return;
else if ( n == SOME_CONST ) throw new UnsupportedOperationException();
else myMeth(n - 1);
}
(The second condition n == SOME_CONST is just there to make the point that sometimes an exception can occur, sometimes it does not).
Suppose I call myMeth(10), and that the exception does happen after a few recursive calls (say SOME_CONST == 5).
Is there any trick I could do (with try-catch block, that is) to get me back to the first frame of myMeth ?

This could work, there is probably a cleaner solution out there, but it's a start:
public static void myMeth(int n, boolean firstCall)
{
// do something
// now execute the recursive call
try
{
if (n < 0) return;
else if ( n == SOME_CONST ) throw new UnsupportedOperationException();
else myMeth(n - 1, false);
}
catch(UnsupportedOperationException e)
{
if (firstCall)
{
//logic
}
else
{
throw e;
}
}
}

try{
myMeth(n);
catch (UnsupportedOperationException e) {
myMeth(n); //or another number
}

Using another static variable to keep track of the first number (10)
static int SOME_CONST = 5;
static int keepN;
public static void myMeth(int n) {
// do something
// now execute the recursive call
try {
if (n < 0) {
return;
} else if (n == SOME_CONST) {
throw new UnsupportedOperationException();
} else {
myMeth(n - 1);
}
} catch (UnsupportedOperationException e) {
if (n == keepN) {
System.out.println(e);
System.out.println("YES first frame");
} else {
System.out.println("NO");
throw e;
}
}
}
public static void main(String[] args) {
keepN = 10;
myMeth(10);
}

// depth should be 0 on first call
public static boolean myMeth(int n, int depth)
{
// do something
// now execute the recursive call
if (n < 0) return true;
else if ( n == SOME_CONST ) return false;
boolean success = myMeth(n - 1, depth + 1);
if (depth == 0 && !success) {
// uh-oh
}
return success;
}
Or if you don't care about each individual frame in the recursion, replace depth with a boolean and change to boolean success = myMeth(n - 1, false);
I'm not sure what you're asking when you say you want to get back to the first frame though. Do you want to go back to the beginning of the first method call, so you can repeat the steps in the // do something block? Or are you fine executing right after the recursive call to myMeth?
If you're generating the Exception yourself, I replaced the need for that by using booleans. If not, you can replace it. You could also just throw an exception in the first frame, while still using booleans.

Yes, but this kind of trick will miss the whole concept of the recursive and will be hard to read and understand.
You shouldn't use recursive if you can't expect the definite number of options it can produce.
Otherwise use another solution.

Related

returning a boolean value from a recursive method

this is a supplementary question aligned to a question I asked recently. I have the following recursive code that will give me the largest number from a List of integers
static int maximum (List<Integer> a)
{
if ((a.getTail().isEmpty()))
return 0;
else {
int n = maximum(a.getTail());
System.out.println(n);
if (a.getHead() > n) {
return (a.getHead());
} else {
return m;
}}
}
This is helpful. But what I really want to do is to be able to return a Boolean value true or false depending on where the list increases in value or decreases. So my method would become:
static boolean maximum (List<Integer> a)
{
if ((a.getTail().isEmpty()))
return true;
else {
int n = maximum(a.getTail());
System.out.println(n);
if (a.getHead() > n) {
return true;
} else {
return false;
}}
}
But this will not run. The challenge I am faced with is that the recursive call as I have written returns an integer so that I can compare the previous maximum with the current maximum ----- if (a.getHead() > m).
What I want to do is to try and complete the assessment of the current verses previous max within the recursive call so that I only have to return a Boolean, true or false.
So for example if as the recursion occurs the list continually increases then the Boolean stays true but if at any point it decreases then it will give a false:
1,2,3,4 = true
1,2,4,3 = false
Thank you for your help I am really struggling with the whole concept of recursion.....
Some things you might have missed:
in a function, a return statement terminates (break) the function immediatly. So in
if(...) { return ...; }
else {...}
→ else is redundant, as if the condition is true, the function is already terminated (break)
Something like a==0 has a boolean value (true or false). So
if(i==0) { return true; }
else { return false; }
can be shortened to return count==0;
I recommend to always use braces, because something like if(i==0) ++i; break;, means if(i==0) {++i;}. break; will be called in any case.
what you want, is something like this:
static boolean is_sorted(List<Integer> list)
{
return is_sorted_from(0, list);
}
static boolean is_sorted_from(int index, List<Integer> list)
{
if(index+1 >= a.size()) { return true };
return list.get(index) < list.get(index+1)
&& is_next_sorted(index+1, list);
}
static boolean maximum (List<Integer> a, boolean cont){
if(cont){
if ((a.getTail().isEmpty())){
cont = false;
}else {
int n = maximum(a.getTail());
System.out.println(n);
if (a.getHead() > n) {
maximum(a.getHead(), cont);
} else {
maximum(n, cont);
}
}
}
return cont;
}
I'd say to make the method void or return the List, but I left it as boolean since that is technically what your question asked for.
You would just call the method with cont having the value of true. By using two parameters, you can continue comparing your max function while simultaneously using a boolean as your recursion flag. You would not be able to return your maximum however, but you could work around this by setting the maximum to either a class instance or to an object that you have as your third parameter (Double, Integer, etc.).

Break Iteration of Java loop with control flow with a recursive method

My attempt at recursion by trying to solve the monkey/coconut/sailor problem.
Im having issues with my for loop stopping. It just iterates though and im unsure where I went wrong.
in my 3 test cases the method testCoconuts returns the values I would like, however my loop will iterate until the last number, even if the true values are sent through the loop.
im sure its my booleans, but i havent been able to figure out what im doing wrong.
public class Test {
public static boolean testCoconuts(int s, int sr, int c){
if (c % s == 1 && sr > 0) {
Test.testCoconuts(s, sr - 1, c - (c/s) - 1);
}
else if (c % s != 1) {
return false;
}
else if (sr == 0) {
System.out.println("solved");
return true; //returns true in all 3 test cases below
}
return false;
}
public static void main(String[] args) {
//int s and sr must me entered into the test program
//as the same number, ex s= 2, sr = 2
int sailors = 3;
Test.testCoconuts(2, 2, 7); //will print solved
Test.testCoconuts(3, 3, 79); //will print solved
Test.testCoconuts(4,4,1021); //will print solved
for (int testNuts = 1; testNuts < 100; testNuts++) {
if (Test.testCoconuts(sailors, sailors, testNuts)==true) {
System.out.println("solved!");
break;
}
else {
System.out.println(testNuts);
System.out.println("next iteration");
System.out.println(testNuts);
}
}
}
}
The for-loop will run until the testCoconouts method equals true.
Now if you take a look at the method, there are four possible outcomes:
if (c % s == 1 && sr > 0)
else if (c % s != 1)
else if (sr == 0)
none of the above was satisfied
However, only in the last three of them have you explicitly stated what value the method should return.
So - in the first outcome, since nothing else is said, the method will always return false as stated outside of the if-statements. I assume you want to return the result from the recursion itself, right?
Try changing the first if-statement like this and see what happens :)
if (c % s == 1 && sr > 0) {
boolean result = Test.testCoconuts(s, sr - 1, c - (c/s) - 1);
return result;
}
(Could be done in a one-liner without the variable result, but I splitted it up for clarity)
Please remember that you call your function recursively and sending a return back to the previous function call, not to the main
Here is a solution:
public class Test {
public static boolean testCoconuts(int s, int sr, int c){
boolean flag = false;
if (c % s == 1 && sr > 0){
flag = Test.testCoconuts(s, sr - 1, c - (c/s) - 1);
}
else if (c % s != 1){
return flag;
}
else if (sr == 0){
System.out.println("solved");
return true; //returns true in all 3 test cases below
}
return flag;
}
public static void main(String[] args){
//int s and sr must me entered into the test program
//as the same number, ex s= 2, sr = 2
int sailors = 3;
//Test.testCoconuts(2, 2, 7); //will print solved
//Test.testCoconuts(3, 3, 79); //will print solved
//Test.testCoconuts(4,4,1021); //will print solved
for (int testNuts = 1; testNuts < 100; testNuts++){
boolean flag = Test.testCoconuts(sailors, sailors, testNuts);
System.out.println(testNuts);
if (flag==true){
System.out.println("solved!");
break;
}
else{
System.out.println(testNuts);
System.out.println("next iteration");
System.out.println(testNuts);
}
}
}
}

Base condition in recursive methods

I am wondering about the base condition in the recursive methods. in my lectures I see that my teacher some times write the base condition in various ways. See this please :
Here the base condition in the public method
public E find(E x) {
if (x == null) {
return null;
}
return find(root,x);
}
private E find(BinaryNode<E> n, E x) {
if (n.element.equals(x)) {
return n.element;
}
else if (x.compareTo(n.element) < 0) {
return find(n.left, x);
}
else {
return find(n.right, x);
}
}
is it OK if I write the base condition in the private method like this :
public E find(E x) {
return find(root,x);
}
private E find(BinaryNode<E> n, E x) {
if (n == null) {
return null;
}
else if (n.element.equals(x)) {
return n.element;
}
else if (x.compareTo(n.element) < 0) {
return find(n.left, x);
}
else {
return find(n.right, x);
}
}
Well, I would pick the following version:
public E find(E x) {
return find(root,x);
}
private E find(BinaryNode<E> n, E x) {
if (n == null) {
return null;
}
else if (n.element.equals(x)) {
return n.element;
}
else if (x.compareTo(n.element) < 0) {
return find(n.left, x);
}
else {
return find(n.right, x);
}
}
Why? Because it's correct. The other one isn't and would lead to the NullPointerException in case there is no such element in the tree.
The second question which appears in the OP post and the comment is whether to put the base condition in a public or a private method. The only possible correct answer is that each recursive method must have a base condition on which the recurrence will end.
public methods can be called by everyone so they should validate the input. They cannot assume that the parameters are valid. private methods can assume that parameters are ok and can focus on their logic.
The condition I would put in your public method would be:
public E find(E x) {
if (<x isn't valid - for example null and nulls are not allowed for values>) {
//do something here - exception or null
}
return find(root,x);
}
It would stand for making sure that the input for the private find...` would be correct. That's what you have to do.

Where it is possible to write the base condition in the recursive methods

I was reading about recursive methods in java ... I do not undserstand the base condition of the recursive method ... Here are two examples
public int weight() {
return weight(root);
}
/ * Returns the weight of the tree where n is the root. * /
private int weight(Node n) {
if (n == null) {
return 0;
} else if (n.left == null) { // då är n.right också null
return n.data;
} else {
return weight(n.left) + weight(n.right);
}
}
public boolean isMobile() {
if (root == null) {
return true;
} else {
return isMobile(root);
}
}
/ * Returns true if the tree where n is the root of a mobile. * /
private boolean isMobile(Node n) {
if (n.left == null) { // då är n.right också null
return true;
} else {
return isMobile(n.left) && isMobile(n.right) &&
weight(n.left) == weight(n.right);
}
}
My wonder : in the weight() method why do not we do like this :
public int weight() {
if (root == null) {
return 0;
} else {
return weight(root);
}
}
As you can see the base condition in the isMobile() method is directly under it but the base condition in the weight() method is under the private method ..
When it is possible to write the base condition of the recursive directly under it or in a separate private method ?
Thanks
EDIT :
public int weight() {
if (root == null) {
return 0;
} else {
return weight(root);
}
}
private int weight(Node n) {
if (n == null) {
return 0;
} else if (n.left == null) { // då är n.right också null
return n.data;
} else {
return weight(n.left) + weight(n.right);
}
}
in the weight() method why do not we do like this : [...]
The simple answer is because parameterless weight() overload of the method is not recursive, even though it relies on a recursive implementation that takes Node as its parameter. The base condition must be in the recursive method itself, because that is where the decision to stop calling itself must be made.
Despite being overloads of the same name, your two weight methods work together like this:
public int nonRecursiveWeight() {
return recursiveWeight(root);
}
private int recursiveWeight(Node n) {
...
}
The nonRecursiveWeight provides a nice public "front" for the recursive implementation recursiveWeight, hiding the node from the API users.
isMobile pair of methods follows the same arrangement: you have a recursive implementation, and a non-recursive "front" sharing the same name.
Base condition must be in the recursive method. The method weight() is not recursive as it is not calling itself. It is calling a recursive method weight(Node n) which has and must have base condition.
if (n == null) { return 0; }
Intention in the isMobile() and isMobile(Node n) is a bit different. The author probably wanted to check for root == null directly in isMobile() method to avoid double checks in recursive method but they can be rewritten like this:
public boolean isMobile() {
return isMobile(root);
}
private boolean isMobile(Node n) {
if ( n == null || n.left == null ) return true;
return isMobile(n.left) && isMobile(n.right) && weight(n.left) == weight(n.right);
}
Again isMobile(Node n) is recursive and isMobile() is not. The isMobile methods now look the same as weight methods. In general the rule is that the recursive methods are the ones which call themselves and they must have base condition which will terminate recursion.
Also please note that you do not need to write else if you have a return before that. For example:
boolean someMethod() {
if ( something ) {
return true;
} else {
return false;
}
}
Can be rewritten as:
boolean someMethod() {
if ( something ) {
// ...
return true;
}
// if something was true then the next piece of code will never get executed
// if was not true then the next piece of code will always execute
// ...
return false;
}
You probably meant if (root == null) in your re-write.
You still have to check in weight(Node) since it's recursive–why do it twice?

How to make one display in a recursive method

I am building a java program that executes from console, at the code I have 2 methods. first that displays all the recursive function and the second one just displays the result.
How to display just the result or where should I add the display?
public static int fibonacciR(int n) {
if(n == 0){
System.out.println(0);
return 0;
} else if(n == 1){
return 1;
}
else{
return fibonacciR(n - 1) + fibonacciR(n - 2);
}
}
First you should delete the System.out.println statement in the recursive function. So it becomes:
public static int fibonacciR(int n) {
if(n == 0){
//You removed the statement here!
return 0;
} else if(n == 1){
return 1;
}
else{
return fibonacciR(n - 1) + fibonacciR(n - 2);
}
}
Now in your main method:
public static void main (String[] args) {
...
System.out.println(fibonacciR(someNumber)); //Here you print the result of the method
...
}
Basically what you should do is remove all the print statements in the method and put it in main.

Categories