What is the difference between:
if ((x <= 19 & x >= 13) ^ (y <= 19 & y >= 13))
{
System.out.print(true);
}
else
{
System.out.print(false);
}
and
if (x <= 19 && x >= 13 || y <= 19 && y >= 13)
{
System.out.print(true);
}
else
{
System.out.print(false);
}
Could you please explain me in detail the operator ^ ?. Please provide some examples.
^ condition operator is the XOR in more mathematic terms, which stand from Exclusive or. (see this)
So the XOR to return true, your left hand side condition must be different from the right hand side condition otherwise is false.
e.g your condition if ((x <= 19 & x >= 13) ^ (y <= 19 & y >= 13)) will return true only in these two cases:
1) (x <= 19 & x >= 13) is true and (y <= 19 & y >= 13) is false
2) (x <= 19 & x >= 13) is false and (y <= 19 & y >= 13) is true
And will return false only in these two cases:
1) (x <= 19 & x >= 13) is true and (y <= 19 & y >= 13) is true
2) (x <= 19 & x >= 13) is false and (y <= 19 & y >= 13) is false
This will also be useful (is available and in the above link I provide for you)
Related
Hey guys I started programming a year ago and recently discovered streams. So I decided to complete my old tasks using streams whenever I could just to get used to them. I know it might not be smart to force using them but it's just practice.
One of my old tasks was to program Minesweeper and right now I try to find a better solution for counting adjacent mines whenever I click a field.
Some details:
I saved a bunch of mines in a Mine[] (arsenal.getArsenal()) and each of the mines has an x and y value. Whenever I click on a field I need to count all mines around the clicked field (from x-1,y-1 till x+1,y+1).
My current solutions are:
private int calculateNearby(int x, int y) {
return (int) Arrays.stream(arsenal.getArsenal())
.filter(mine -> mine.getX() == x + 1 && mine.getY() == y
|| mine.getX() == x && mine.getY() == y + 1
|| mine.getX() == x - 1 && mine.getY() == y
|| mine.getX() == x && mine.getY() == y - 1
|| mine.getX() == x - 1 && mine.getY() == y - 1
|| mine.getX() == x - 1 && mine.getY() == y + 1
|| mine.getX() == x + 1 && mine.getY() == y - 1
|| mine.getX() == x + 1 && mine.getY() == y + 1)
.count();
}
private int calculateNearby(int x, int y) {
return (int) Arrays.stream(arsenal.getArsenal())
.filter(mine ->
{
boolean b = false;
for (int i = -1; i < 2; ++i) {
for (int j = -1; j < 2; ++j) {
if ((x != 0 || y != 0) && mine.getX() == x + i && mine.getY() == y + j) {
b = true;
}
}
}
return b;
})
.count();
}
Both solutions work fine but the first looks "wrong" because of all the cases and the seconds uses for-loops which I basically tried to avoid using.
It would be nice if you could show me a better (ideally shorter) solution using streams. :D
I'm sorry if there's already a thread about this. I really tried to find anything related but there either isn't anything or I searched for the wrong keywords.
You can simplify your stream condition. Instead of checking each case if getX() equals x, x-1 or x+1 you can just check if getX() is greater or equals than x-1 and smaller or equals x+1. The same for getY().
return (int) Arrays.stream(arsenal.getArsenal())
.filter(mine -> mine.getX() >= x - 1 && mine.getX() <= x + 1
&& mine.getY() >= y - 1 && mine.getY() <= y + 1)
.count();
You could also create a method for the check to make the code more readable.
private int calculateNearby(int x, int y) {
return (int) Arrays.stream(arsenal.getArsenal())
.filter(mine -> inRange(mine.getX(), x)
&& inRange(mine.getY(), y))
.count();
}
private boolean inRange(int actual, int target) {
return actual >= target - 1 && actual <= target + 1;
}
Another way is to check if the absolute distance in each direction is less than or equal to 1:
private int calculateNearby(int x, int y) {
return (int) Arrays.stream(arsenal.getArsenal())
.filter(mine -> Math.abs(mine.getX() - x) <= 1 && Math.abs(mine.getY() - y) <= 1)
.count();
}
Note that this also counts a mine which is at the point (x, y) which is not the case with the code in the question.
When is a mine adjacent? When its only one field horizontally or vertically away.
Horizontal distance is Math.abs(mine.getX() - x), vertical distance is Math.abs(mine.getY() - y). It doesn't matter if its -1 or 1, just that it is one field away.
But it shouldn't be more than one field, either vertical or horizontal be away, so max(dx, dy) == 1.
Predicate<Mine> isAdjacent = mine ->
Math.max(
Math.abs(mine.getX() - x)
Math.abs(mine.getY() - y)
) == 1;
return (int) Arrays.stream(arsenal.getArsenal())
.filter(isAdjacent)
.count();
I'm unable to get the do-while loop below work in Java. Thanks for your help.
do{
//User enters a value for x
//User enters a value for y
}while(x==-1 && y==-1 || x==5 || y==10);
What I'm trying to do is simply:
a) If x and y BOTH are -1 then terminate the loop
b) If x is 5 OR y is 10 then terminate the loop
You took the problem on the wrong side. There your loop will continue where you want to stop.
You should simply do the following and reverse the condition
do {
} while (!(x == -1 && y == -1 || x == 5 || y == 10));
Demo
public static void main (String[] args) {
System.out.println(conditionTesting(0, -1)); // true
System.out.println(conditionTesting(-1, -1)); // false
System.out.println(conditionTesting(5, -1)); // false
System.out.println(conditionTesting(-1, 10)); // false
System.out.println(conditionTesting(6, 9)); // true
}
public static boolean conditionTesting(int x, int y) {
return !(x == -1 && y == -1 || x == 5 || y == 10);
}
DeMorgan
If you want to go and represent it using DeMorgan's Law, you can do it using the following steps
¬((P ∧ Q) ∨ R ∨ S)
≡¬(P ∧ Q) ∧ ¬R ∧ ¬S
≡(¬P ∨ ¬Q) ∧ ¬R ∧ ¬S
So your final translation would be
(x != -1 || y != -1) && x != 5 && y != 10
Ideone Demo
Maybe I am swatting flies with a sledgehammer but...
I was doing this exerice on CodingBat;
Given 2 ints, a and b, return their sum. However, "teen" values in the range [13, 19] are extra lucky. So if either value is a teen, just return 19.
and this is the answer I came up with;
public int teenSum(int a, int b)
{
if (a >= 13 && a <= 19) return 19;
if (b >= 13 && b <= 19) return 19;
else return a + b;
}
I was wondering if there was a way to solve this problem in just one "if" statement... is there?
If you use a ternary operator (? :) you could do it with zero if statements. Something like,
public int teenSum(int a, int b)
{
return (a > 12 && a < 20) || (b > 12 && b < 20) ? 19 : a + b;
}
You can have a logically equivalent expression using logical OR:
if ((a >= 13 && a <= 19) || (b >= 13 && b <= 19)) return 19;
Sure. By putting two if statements as guard clauses, what you're really doing is a logical OR. So:
if ((a >= 13 && a <= 19) || (b >= 13 && b <= 19)) return 19;
would also work.
By the way, the else is redundant.
You can do it entirely without if statements, using the ?: ternary operator.
return (a >= 13 && a <= 19) || (b >= 13 && b <= 19) ? 19 : a + b;
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
What am I doing wrong here?
I am wanting to display integers from 1-100 who are divisible by either 6 or 7. That's done and working. The next step is to not display any that are divisible by both...that isn't working in my loop (those integers are still displaying)
for (int i = 1; i < 100; i++)
if (i % 6 == 0 || i % 7 == 0 && i % (6 * 7) != 0){
println(i);
}
Thanks!
Joel
try making your condition more explicit by adding (...), like so:
if (((i % 6 == 0 || i % 7 == 0) && (i % (6 * 7) != 0)) {
}
by default && takes precedence over ||
Missing parentheses:
for (int i = 1; i < 100; i++) {
if ((i % 6 == 0 || i % 7 == 0) && i % (6 * 7) != 0) {
println(i);
}
}
You could also use the exclusive or
for (int i = 1; i < 100; i++) {
if ((i % 6 == 0) ^ (i % 7 == 0)) {
println(i);
}
}
or just an unequal if ((i % 6 == 0) != (i % 7 == 0))
Since exclusive or is not used that often, I doubt this will increase the readability of the code...
I would simply stop worrying about how to evaluate precedence, and use something like:
for (int i = 1; i <= 100; i++) {
if ((i % 42) == 0) continue;
if ((i % 6) == 0) println (i);
if ((i % 7) == 0) println (i);
}
I'm assuming here that 1-100 was an inclusive range in which case you should use <= rather than <. It won't matter for your specific case since 100 is divisible by neither 6 nor 7.
Guess what? Any decent optimising compiler (including JIT ones) will probably end up generating the same code as for all the other possibilities. And, even if it didn't, it wouldn't matter unless you were calling this function a great many times.
I think that's a tiny bit more readable than:
if (i % 6 == 0 || i % 7 == 0 && i % (6 * 7) != 0) ...
or, worse yet, the Lisp-like thing you'll have to turn it into to get it working properly :-)
Keep in mind one possibility - you can change your loop to make it more efficient (sevenfold), for the specific case with 6 and 7, thus:
for (int i = 7; i <= 100; i += 7)
if ((i % 6) != 0)
println (i);
This uses the for loop itself to only check multiples of 7 and print them if they're not also multiples of 6.
for (int i = 1; i < 100; i++)
if ((i % 6 == 0 || i % 7 == 0) && !(i % 6 == 0 && i % 7 == 0)){
println(i);
}