Complicated if else logic in Java [closed] - java

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 8 years ago.
Improve this question
I have three if statements:
if (!(a == 0 && b == 0)) {...}
if (!(a == 0 && b != 0)) {...}
if (!(a != 0 && b != 0)) {...}
I would like to combine them in one code block such as a method.
I don't want the other statements to run if one has run. There are workarounds if I want to avoid coming up with some good logic but I'd like to know if there is a beautiful way to write that.

if (!(a == 0 && b b == 0)) {...}
truth table
a b r
z n T
n n T
z z F
n z T
for
if (!(a == 0 && b b != 0)) {...}
truth table
z n F
n n F
z z T
n z T
for
if (!(a != 0 && b b != 0)) {...}
truth table
z n T
n n F
z z T
n z T
common case
n z T
so result that works on all 3 condition is
a != 0 && b == 0
note that: all 3 conditions are totally different, this will only work if you care to execute if
(first && second && third) is true
validate all case by yourself
(z = zero, n = non zero, a, b variables, r = result, T = true, F = false)

Simplest way to express this:
public int foo(boolean a, boolean b) {
int result;
if (a) {
if (b) { result = 1; }
else { result = 2; }
else {
if (b) { result = 3; }
else { result = 4; }
return result;
}
(notice that this evaluates a and b once each, which is the minimum you can expect here)
To keep #DavidWallace happy, here's a translation to the particular form of the original question:
public int foo(int a, int b) {
int result;
if (a==0) {
if (b==0) { result = 1; } // or whatever should happen, not specified in the question
else { result = 2; }
else {
if (b==0) { result = 3; }
else { result = 4; }
return result;
}

Just to re-word your question. You say that if one block runs, the others shouldn't. So when you wrote
if (!(a == 0 && b == 0)) {...}
if (!(a == 0 && b != 0)) {...}
if (!(a != 0 && b != 0)) {...}
You actually meant
if (!(a == 0 && b == 0)) {
// first ...
}
else if (!(a == 0 && b != 0)) {
// second ...
}
else if (!(a != 0 && b != 0)) {
// third ...
}
But this is equivalent to
if (a != 0 || b != 0) {
// first ...
}
else if (b == 0) {
// second ...
}
Notice that the third ... can never run, as I stated in my comment.

Related

What is difference between using logical operators using parentheses?

I am getting different results: -1 if I use parentheses and 1 if I don't use parentheses.
For test case "30/10/2019" I am getting -1 if I use parentheses and 1 if I don't use parentheses in the following line:
else if((mm==1||mm==3||mm==5||mm==7||mm==8||mm==10||mm==12) && mm<13 && mm>0 && dd>0 && dd<32) return 1;
What is the difference between above line and below line?
else if(mm==1||mm==3||mm==5||mm==7||mm==8||mm==10||mm==12 && mm<13 && mm>0 && dd>0 && dd<32) return 1;
public class Utility {
public static int checkDate(String date){
String []st;
if((date.charAt(2)=='.' && date.charAt(5)=='.')||(date.charAt(2)=='/' && date.charAt(5)=='/')||(date.charAt(2)=='-' && date.charAt(5)=='-'))
{
String token = Character.toString(date.charAt(2));
if(date.charAt(2) == '.') st = date.split("\\.");
else st = date.split(token);
int dd = Integer.parseInt(st[0]);
int mm = Integer.parseInt(st[1]);
int yy = Integer.parseInt(st[2]);
if(mm == 2 && dd>0 && dd<30 && mm<13 && mm>0) return 1;
else if((mm==1||mm==3||mm==5||mm==7||mm==8||mm==10||mm==12) && mm<13 && mm>0 && dd>0 && dd<32) return 1;
else if((mm==4||mm==6||mm==9||mm==11) && dd>0 && dd<31 && mm<13 && mm>0) return 1;
else return -1;
}
else return -1;
}
}
import java.util.Scanner;
public class DateValidation {
public static void main(String[] args) {
// STUDENT CODE BEGINS HERE
Scanner sc = new Scanner(System.in);
String dt=sc.next();
Utility ut = new Utility();
int flag = ut.checkDate(dt);
if(flag==1)
System.out.println("Valid");
else
System.out.println("Invalid");
// STUDENT CODE ENDs HERE
}
}
It will execute the following (in highest order of precedence):
Parentheses ()
Not !
And &&
Or ||
else if((mm==1||mm==3||mm==5||mm==7||mm==8||mm==10||mm==12) && mm<13 && mm>0 && dd>0 && dd<32)
return 1;
It will evaluate (mm==1||mm==3||mm==5||mm==7||mm==8||mm==10||mm==12) first, then && mm<13 && mm>0 && dd>0 && dd<32
else if(mm==1||mm==3||mm==5||mm==7||mm==8||mm==10||mm==12 && mm<13 && mm>0 && dd>0 && dd<32)
return 1;
As for the other, it will evaluate mm<13 && mm>0 && dd>0 && dd<32 first, then mm==1||mm==3||mm==5||mm==7||mm==8||mm==10||mm==12 &&
Parentheses decide the order these booleans are resolved. And binds stronger than Or. In your case you ask for:
mm==12 && mm<13
So left comparison and right comparison must resolve to true. They don't, as you are in month 10. With parenthesis you decide to check if your month value is valid at all, this resolves to true, and then the && check resolves to true as well.
Consider this example.
int a = 5;
System.out.println((a == 5 || a == 10) && a == 8 || a == 9); // false
// evaluates to true && false || false which is false
System.out.println(a == 5 || a == 10 && a == 8 || a == 9); // true
// evaluate to true || false && false && false
// the first true, wins because it is followed by an || so the whole
// expression evaluates to true.
With a && b both both a and b must be true for the statement to be true
With a || b only one of a and b must be true.
This also goes for grouped expressions.
If one expression is true and the other is false, the complete expression is false for && and true for ||. These operators work from left to right so you need to group appropriately, just like arithmetic expressions.
The best advice is always use parentheses to ensure proper evaluation of expressions.

Greatest common divisor

I try to find the greatest common divisor for two integers. But I don't understand what is wrong with my code:
public class Main {
public static void main(String[] args) {
Scanner s = new Scanner(System.in);
int a = s.nextInt();
int b = s.nextInt();
while (a != 0 | b != 0) {
if (a >= b) {
a = a % b;
} else {
b = b % a;
}
}
if (a == 0) {
System.out.println(b);
} else {
System.out.println(a);
}
}
}
Just change
a != 0 | b != 0
to
a != 0 && b != 0
Because you version will be work even a or b equals 0.
But you need to exit from loop when one of them equals 0.
&& - better than & because in your case you don't need to check
right-hand operator if left equals 0
It is easier to calculate the GCD if we understand the core logic. Try to understand what we need to do, and how we are going to do it before implementing the program.
What we are trying to find is the greatest number that divides both a and b.
So the question arises that how we are going to do it. We do a loop just like you did, but for this case, let's initially assume that a is greater than b.
The first step is to start the loop, while the calculation is not finished. The condition in our case is, we have to stop when any one of the two numbers becomes zero.
while (a != 0 && b != 0)
{
// Do the calculation here.
}
Now we have to write the calculation. We have assumed that a is greater than b or both are equal.
We keep on assigning the remainder of a divided by b to a.
while (a != 0 && b != 0)
{
a = a % b;
}
This makes the solution only half correct, we will have to deal with the other case, that is when b is greater than a. Why this happens is after some set of iterations, a will become less than b, and that will result in a being set to 0.
So let's do the same solution to the other case, when a is less than b.
while (a != 0 && b != 0)
{
if (a > b)
a = a % b;
else
b = b % a;
}
And this is what you wanted to achieve. The non-zero value will be the solution.
Let's just not stop here, and see why your current version does not work. You have had this in your condition.
Your condition is:
a != 0 | b != 0
Here, you are using bit-wise operator OR, between two boolean values, which comes to the following. Assume any of a and b is zero.
Case 1:
a != 0 => true
b != 0 => false
true | false => true
Case 2:
a != 0 => false
b != 0 => true
false | true => true
Therefore as you see in the above cases, it continues to loop until both becomes zero, and hence you will always be reported as the GCD is zero.
Hope this helps.
You probably need to implement the Eudidean's Algorithm (which is actually about the math) But here is an example of how does this alg works
private static int GCD(int a, int b)
{
int remainder = a % b;
while (remainder!= 0)
{
a = b;
b = remainder;
remainder = a % b;
}
return b;
}

Java - While loop where all conditions must be false for it to exit

First of all is this possible? Second of all if it is how can it be done? Im trying to get the following code to work like that but even if one of the variables is 0 it exits the loop, it needs to be made that all 3 variables are less than 1 for it to exit
import java.util.Scanner;
public class BabyNim
{
public static void main(String[] args)
{
Scanner keyboard = new Scanner(System.in);
int a, b, c, input;
String pile;
a = 3;
b = 3;
c = 3;
System.out.println("A: " + a + "\tB: " + b + "\tC: " + c);
while (a > 1 && b > 1 && c > 1)
{
System.out.print("Pile: ");
pile = keyboard.next();
System.out.print("How many to remove: ");
input = keyboard.nextInt();
switch (pile) {
case "a": {
a = a - input;
}case "b": {
b = b - input;
}case "c": {
c = c - input;
}
}
}
}
}
while (a >= 1 || b >= 1 || c >= 1)
it needs to be made that all 3 variables are less than 1 for it to exit
Like that, this is what is needed so that it exits, right?
a < 1 && b < 1 && c < 1
So, negate it:
!(a < 1 && b < 1 && c < 1)
Which can be written like this:
a >= 1 || b >= 1 || c >= 1
As others posted, you had a problem on your switch block that hadn't a break; after each condition. At least if that wasn't the intention.
The problem looks to be your switch: statement. If I remember correctly you need to put a 'break;' at the end of each case statement, otherwise you run the possibility of "falling through" other case criteria.
Also you have to examine the order of operations when using a boolean for a conditional. while( a > 1 && b > 1 && c > 1) will short circuit to false when a < 1. you may be looking for a mix of your condition and the one offered by #Andy Turner:
while(a>=1 && b>=1 && c >=1)

Straight hand in Java poker game

I am having trouble finishing the straight method for a poker hand. I don't understand why my code doesn't work.
public static boolean containsStraight(int [] hand)
{
boolean straight = false;
for(int i = 0; i < 5; i++)
{
if (hand[i] == 2 && hand[i] == 3 && hand[i] == 4 && hand[i] == 5 && hand[i] == 6)
{
straight = true;
}
if (hand[i] == 3 && hand[i] == 4 && hand[i] == 5 && hand[i] == 6 && hand[i] == 7)
{
straight = true;
}
if (hand[i] == 4 && hand[i] == 5 && hand[i] == 6 && hand[i] == 7 && hand[i] == 8)
{
straight = true;
}
if (hand[i] == 5 && hand[i] == 6 && hand[i] == 7 && hand[i] == 8 && hand[i] == 9)
{
straight = true;
}
}
return straight;
}
As pL4Gu33 has already stated in his answer, your comparison is faulty. Essentially, each step through the for-loop leaves hand[i] at a constant value (say, 4). That means that your if-statements are checking:
if(4 == 4 && 4 == 5 && 4 == 6 && 4 == 7 && 4 == 8) {
...
}
This will never evaluate to true. If you knew for certain that you had five elements in the hand and that the hand was already sorted, you could do
if (hand[0] == 2 && hand[1] == 3 && hand[2] == 4 && hand[3] == 5 && hand[4] == 6) {
...
}
However, I'm going to show you a better answer.
The first thing you should do is to sort your hand. Once you do that, it's easy to step through the hand and check to see if the next card in the hand is exactly one greater than the previous card. If you get to the end and this holds true, then it's a straight.
/*
* You will need to import java.util.Arrays
*/
public boolean isStraight(int[] hand) {
if(hand == null || hand.length != 5) {
return false;
}
else {
// Automatically sort the hand
Arrays.sort(hand);
// Set the "previous" variable to a theoretically impossible value
int prev = -1;
// Iterate through the hand and see if the next card is exactly one more than
// the previous one.
for(int i = 0; i < hand.length; i++) {
// If prev is -1, then this is the first time through the for-loop
// If the card that we're on has a value of the previous card + 1,
// we still have the possibility of a straight.
if(prev == -1 || (prev + 1) == hand[i]) {
prev = hand[i];
}
else {
return false;
}
}
return true;
}
}
You say in every iteration hand[i] must be 2 AND 3 AND 4 AND 5. That is impossible. There is only one number in hand[i].
The problem is, that you are using the cycle incorrectly, because you are always checking the value of the same card in hand[i]. My suggestion would be either to do a sort first, or if you want to be more efficient, you can use a second field of booleans, that would indicate, whether a card of given value is present in your hand. This way you can easily check, if you have any number of cards in succesion.
public static boolean containsStraight(int[] cards) {
int count = 0;
boolean[] valueInHand = new boolean[10];
for (int card : cards) {
valueInHand[card] = true;
}
for (boolean value : valueInHand) {
if (value == true) {
count++;
} else {
count = 0;
}
// works for any number of cards
if (count == cards.length) {
return true;
}
}
return false;
}

JAVA - Figuring out the difference

I'm given the problem below, however I'm unable to have it pass all the tests no matter what approach I take. Could anyone point out where I'm going wrong?
The problem has to be solved using Math.abs() and IF statements, no loops/functions/etc.
////////////////////////////// PROBLEM STATEMENT //////////////////////////////
// Given three ints, a b c, print true if one of b or c is "close" //
// (differing from a by at most 1), while the other is "far", differing //
// from both other values by 2 or more. Note: Math.abs(num) computes the //
// absolute value of a number. //
// 1, 2, 10 -> true //
// 1, 2, 3 -> false //
// 4, 1, 3 -> true //
///////////////////////////////////////////////////////////////////////////////
My code:
if ((Math.abs(a-b) <= 1 || Math.abs(a+b) <= 1) && (Math.abs(a-c) >= 2 || Math.abs(a+c) >= 2)) {
if (Math.abs(a-c) >= 2 || Math.abs(a+c) >= 2) {
System.out.println("true");
} else {
System.out.println("false");
}
} else if (Math.abs(a-c) <= 1 || Math.abs(a+c) <= 1) {
if (Math.abs(a-b) >= 2 || Math.abs(a+b) >= 2) {
System.out.println("true");
} else {
System.out.println("false");
}
} else {
System.out.println("false");
}
Seems overly complex, you might want to go for something more simple:
boolean abIsClose = Math.abs(a-b) <= 1;
boolean acIsClose = Math.abs(a-c) <= 1;
boolean bcIsClose = Math.abs(b-c) <= 1;
boolean result = abIsClose && !acIsClose && !bcIsClose;
result = result || (!abIsClose && acIsClose && !bcIsClose);
result = result || (!abIsClose && !acIsClose && bcIsClose);
Abs always gives a positive number, that way you don't need to confirm a value is between -1 and 1, you only need to confirm <= 1.
You can break this down into two possible situation when it's true
b is close and c is far
c is close and b is far
Now, what does 1. mean?
b is close - Math.abs(a-b) <= 1
c is far - Math.abs(a-c) >= 2 && Math.abs(b-c) >= 2
So we end up with
if (Math.abs(a - b) <= 1 && Math.abs(a - c) >= 2 && Math.abs(b - c) >= 2) {
return true;
}
Now apply the same logic to the second condition:
if (Math.abs(a - c) <= 1 && Math.abs(a - b) >= 2 && Math.abs(b - c) >= 2) {
return true;
}
So the final method looks like:
public static boolean myMethod(int a, int b, int c) {
if (Math.abs(a - b) <= 1 && Math.abs(a - c) >= 2 && Math.abs(b - c) >= 2) {
return true;
}
if (Math.abs(a - c) <= 1 && Math.abs(a - b) >= 2 && Math.abs(b - c) >= 2) {
return true;
}
return false;
}
Output:
public static void main(String[] args) {
System.out.println(myMethod(1, 2, 10));
System.out.println(myMethod(1, 2, 3));
System.out.println(myMethod(4, 1, 3));
}
true
false
true

Categories

Resources