How do I break out of this recursive call? - java

I am a newbie to recursion and I am still learning it, so please tolerate my poor logic if it is bad. I have this function which has 5 parameters a,b,c,x,y. so what I essentially want to do is take an element out of either of these variables and add it to the other to finally get x , y. I want to try out this by myself and I have nearly done it, only i wanted to ask if there's any way i could get out of this recursive call, once I get the answer as "YES".
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
String in = sc.nextLine();
int[] input = new int[10];
for(int i=0; i < 10; i=i+2) {
input[i] = Integer.parseInt(String.valueOf(in.charAt(i)));
}
int A = input[0];
int B = input[2];
int C = input[4];
int X = input[6];
int Y = input[8];
persistent(A,B,C,X,Y);
}
private static void persistent(int a, int b, int c, int x, int y) {
if(a == 0 || b == 0 || c == 0) {
if((a == x && b == y) && (b == x && a == y)) {
System.out.println("YES");
}
else if((b == x && c == y) || (c == x && b == y)) {
System.out.println("YES");
}
else if((a == x && c == y) && (c == x && a == y)) {
System.out.println("YES");
}
else {
return;
}
}
persistent(a-1,b+1,c,x,y);
persistent(a-1,b,c+1,x,y);
persistent(a+1,b-1,c,x,y);
persistent(a,b-1,c+1,x,y);
persistent(a+1,b,c-1,x,y);
persistent(a,b+1,c-1,x,y);
}

Your code never does.
Recursive algorithms pretty much all boil down to this exact same style:
First, check if some edge case has been reached (generally, the very simplest case). In this case, return immediately - do not recurse. By tautology, if the answer is so easy you can just give it without needing to recurse, that defines 'edge case' / 'simple case'. There must be at least one such case, or a recursive algorithm cannot work.
Otherwise, provide your answer and feel free to employ as many recursive calls as you prefer, but every single last one of those calls must be simpler, defined by the idea that it is strictly closer to that simple case as mentioned in 1.
All state is conveyed via parameters. It is common to have a private helper method that does the actual work which has a bunch of extra parameters, and the public API that is a one-liner that calls the helper, providing initial values for those extra parameters. Only if you have no such state can you omit this one.
Your code isn't doing this. There is a simple case, which is if a or b or c is 0, but your 6 recursive calls are not clearly moving towards simplicity.
The fix is not obvious. Your algorithm cannot work as written and cannot be fixed without considerably rethinking it.
Hopefully the above will help you: Your recursive calls need to become simpler somehow, guaranteed. Right now it's not guaranteed: Yes, every call is moving one of the 3 numbers closer to the edge case (be 0), but there is no clear flow: If I call your code with, say, 3/4/5 as arguments, then it makes recurisve calls with 2/5/5, 2/4/6, etcetera. That first call (2/5/5) is not moving guaranteed closer to the edge case, because as part of its call stack, it'll be doing 3/4/5 again.

Related

Can someone explain the "static" requirement for my code?

I am working through hackerrank and I felt pretty solid about my code, but it doesn't work. Evidently, it has something to do with the way that I named the variables. Ultimately, the goal was to output the area of a rectangle if the area is positive, and if not,
System.out.println("java.lang.Exception: Breadth and height must be positive")
This was my code:
int B = scan.nextInt();
int H = scan.nextInt();
scan.close();
Boolean correct = (B > 0) || (H > 0);
if(correct){
int area=B*H;
System.out.print(area);
}
else correct = false;
System.out.println("java.lang.Exception: Breadth and height must be positive");
scan.close();
This is the code that actually works:
private static int B;
private static int H;
private static boolean flag;
static {
Scanner scan = new Scanner(System.in);
B = scan.nextInt();
H = scan.nextInt();
scan.close();
if (B <= 0 || H <= 0) {
System.out.println("java.lang.Exception: Breadth and height must be positive");
flag = false;
} else {
flag = true;}
I expected the input of negative integers to output the Breadth and height error, but instead it outputs
20java.lang.Exception: Breadth and height must be positive
Rather than using someone else's code (the second example), I would really like to fix my own code idea and understand the use of the static class better.
First, your condition should contain and AND not an OR. The input is correct if both the height and the width are positive.
Second, you have missed out braces after the else, so the println happens in all cases.
Also:
You don't need to use Boolean, you can use boolean.
You don't need to set correct to false after the else. In fact, you don't need it at all.
Your indentation is wrong. It is much harder to get your code right if it is not indented correctly.
Java variables should be lower case (b and h, not B and H).
Practice spending a bit more time reviewing your own code and learning how to debug it because these are very basic errors. It will help you a lot.
Your condition sould use && insteed of ||. Ans since you dont put {} to the else it only affect the correct = false; and not the print.err
int B = scan.nextInt();
int H = scan.nextInt();
scan.close();
Boolean correct = (B > 0) && (H > 0);
if(correct){
int area=B*H;
System.out.println(area);
} else
System.err.println("java.lang.Exception: Breadth and height must be positive");
scan.close();
You have several problems in your code:
(B > 0) || (H > 0) This condition should use AND instead of OR: (B > 0) && (H > 0)
You forgot curly brackets at your "else" part of code.
Do not "throw exceptions" that way. It's hmm... weird.
This is what you want to do:
if (correct) {
int area=B*H;
System.out.print(area);
} else {
correct = false; //as long as your're throwing exception in this block, this assignment is redundant
scan.close();
throw new Exception("Breadth and height must be positive");
}
P.S. Also to mention. You probably do not want to use a static block to put your code into. Use methods instead. Something like: public int getSquare() { } and place your code inside.

Recursion in java and maintaining states of variables across stacks

I was trying to solve a problem in BST where the question was "Check if all leaves are at same level"
In this question, I need to keep incrementing the level per stack call but also maintain a value across all calls, the maximum level. Along with this, I need to return a boolean with the result.
It is simple enough to solve, I need to keep doing down the tree, I did this
int maxlevel = 0;
public boolean allAtSameLevel(Node root, int level){
if(root== null){
return false;
}
if(root.left== null && root.right == null){
if(maxlevel == 0){
maxlevel = level;
}
return(level== maxlevel);
}
return allAtSameLevel(root.left, level+1) && allAtSameLevel(root.right, level+1) ;
}
My problem is that for a value that needs to be shared, I have to maintain an instance variable in java. Is there a better way to do this? My confusion is that since, it's going to go all the way to the right leaf first and then go up, passing the value won't help. Any ideas?
The trick is to communicate the depth of the subtree back to the higher level of the stack, but doing so only when both right and left depths are the same. You can do it with a simple recursive function:
int eqDepth(Node n) {
if (n == null) return 0; // This is a leaf, its subtree depth is zero
int dLeft = eqDepth(n.left); // Make two recursive calls
int dRight = eqDepth(n.right);
// If one of the depths is negative, or the depths are different,
// report it by returning negative 1:
if (dLeft < 0 || dRight < 0 || dLeft != dRight) return -1;
return 1+dLeft; // It's the same as dRight
}
With this function in hand, you can code allAtSameLevel in one line:
public boolean allAtSameLevel(Node root) {
return eqDepth(root) >= 0;
}
Here is a demo on ideone. It starts off with an unbalanced tree and gets a -1
a
/ \
b c
/ \ / \
d e f -
then adds the missing node
a
/ \
b c
/ \ / \
d e f g
and gets a positive result.

Best DRY if statement?

Let's say I want to compare a bunch of variables to one static variable, normally I would do it like this:
int w = 0;
int x = 1;
int y = 1;
int z = 2;
if(w == x || w == y || w == z){/*more code here*/}
But that can get extremely long and doesn't seem necessary, are there any ways to do something more like:
if(w == (x || y || z)){/*more code here*/}
I would like to think that there is a way to do it like this.
Instead of:
if(w == x || w == y || w == z)
you can do:
if(Arrays.asList(x, y, z).contains(w))
Though there is an answer accepted, I would want to share my ways too:
Method 1 is similar to the accepted answer. However, instead of using List, I use a Set. In such case, it may be even faster than doing == individually if there are lots of values to check against:
// make it a static final member if semantically possible
Set<Integer> ALL_VALUES = new HashSet<Integer>(Arrays.asList(a,b,c,d,e,f,g,h));
//.....
if (ALL_VALUES.contains(w)) {
//... do something
}
Method 2 is to write a little utility function, something like
public static <T> boolean sameAsAny(T value, T... possibleValues) {
for (T p : possibleValues) {
if (value == p) {
return true;
}
}
return false;
}
with such util you can do something like:
if (sameAsAny(w, x, y, z))
You might prefer to format it like this :
if(w == x ||
w == y ||
w == z)
I find it helps break up the conditions and makes it easier to read.
That is not allowed in Java. But you could look into some rules based engines e.g drools.

Java - Double Comparison

How can I do something like:
int a=5;
if(4<=a<=6){
}
in Java?
Make it two conditions:
int a=5;
if(4<=a && a<=6){
}
Apart from the obvious solution stated by others (if(4<=a && a<=6)), you can use commons-lang's IntRange:
Range range = new IntRange(4,6)
if (range.containsInteger(5)) {..}
It looks like a bit of an overkill, but depending on the situation (if it isn't as trivial) it can be very useful.
if(4 <= a && a <= 6) {
// do something
}
Of course, you could always write a function like this in some Util class:
class Util {
public static boolean inclusiveBetween(int num, int a, int b) {
return num >= a && num <= b;
}
}
and then you can do something like
if(Util.inclusiveBetween(someResourceIntensiveOpReturningInt(), 4, 6)) {
// do things
}
You can't, I don't think. What's wrong with
int a = 5;
if(a >= 4 && a <= 6) {
}
? If you need to compare many different variables, put them in an array and sort the array, then compare the arrays.
You can do this. Its ugly, but can be very slightly faster.
int a = 5;
if(a - Integer.MIN_VALUE - 4 <= 2 - Integer.MIN_VALUE) {
}
This exploits the use of underflow to turn two comparisons into one. This can save about 1-2 nano-seconds. However, in some usecases it can cost the same amount, so only try it if you are trying to micro-tune a loop.

Is there a neater way to do this? Java IF

public void moveRowItemToBottomIfAllowed(int r, int f) {
int i = rows[r].peek().getType();
int j = 0;
if (bottom[f].isEmpty()) {
for (int k = 0; k < 4; k++) {
if ((k == f) || (bottom[k].isEmpty()) || (bottom[k].peek().getType() != i)) {
continue;
}
j = 1;
}
if (j == 0) {
bottom[f].push(rows[r].pop());
}
} else if ((!bottom[f].isEmpty()) && (rankTrueFalse(rows[r].peek(), bottom[f].peek())) && (rows[r].peek().getType() == bottom[f].peek().getType())) {
bottom[f].push(rows[r].pop());
}
}
As I'm still learning java I've been putting together some rules for a game, I went through how to do it logically and came up with the above code which works correctly but it looks like a bit of a mess - is there any neater way or a more efficient way of writing this code? any pointers are much appreciated.
I would extract methods to make the code more readable. At first sight I would extract
the for loop, or probably the whole contents of the if block,
the expression from the 2nd long else if
Use descriptive names for your new methods (and for your variables too, for that matter). This makes a huge difference in readability.
I would recommend that you use more descriptive names for your variables. What is r? What is f? I'm guessing that f is some sort of numeric representation of the suit, since you compare it to k, which iterates over four values.
There might be more to say about the code overall, but the first step is to write the code in a self documenting manner.
There are bits of expressions which could be extracted into local variables: rows[r].peek() and bottom[f].peek() being the most obvious ones.
It looks like you are using j as a flag. Booleans are better for that, but you can return early instead of setting the condition that guards the rest of the processing, getting rid of j entirely.
You're double checking that bottom[f].isEmpty()) is false, and can use the already looked up i instead of repeating rows[r].peek().getType()
Both sides of your first condition, if they end up doing the processing, do the same processing, which you can write once:
public void moveRowItemToBottomIfAllowed(int r, int f) {
int i = rows[r].peek().getType();
if (bottom[f].isEmpty()) {
for (int k = 0; k < 4; k++) {
if (k == f) continue;
if (bottom[k].isEmpty()) continue;
if (bottom[k].peek().getType() == i) return;
}
} else {
if (!rankTrueFalse(rows[r].peek(), bottom[f].peek())) return;
if (bottom[f].peek().getType() != i) return;
}
bottom[f].push(rows[r].pop());
}
This code is then structured as a bunch of guards with early exits, followed by the processing.
The guards could then be extracted into their own method, leaving:
public void moveRowItemToBottomIfAllowed(int r, int f) {
if (moveIsAllowed(r,f)) bottom[f].push(rows[r].pop());
}

Categories

Resources