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;
Related
I am making a counter between number ranges and not sure the correct way to do this. I have always used the || operator but reading some examples, I feel I should be using the && command. Here is my example problem...
if(value >= 1 || value <=10){
count1++;
}
else if(value >= 11 || value <= 20){
count2++;
// AND SO ON........
Or should I be using the && operator like
if(value >= 1 && value <= 10){
count1++;
}
else if value >= 11 && value <= 20){
count2++;
}
|| means "or".
&& means "and".
value >= 1 || value <= 10 makes no sense because it's always true. All numbers are 1 or more, or 10 or less. Some numbers are both, but that doesn't matter.
value >= 1 && value <= 10 makes far more sense. There's a limited range of numbers ([1..10]) for which both the first condition and the second condition are true.
|| is the or operator, so the condition value >= 1 || value <=10 is true for all values if you think about it. So, unless you want your counts to be meaningless, use && which is the and operator.
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)
I tried to implement Rot13 and to make it as minimal as possible, this are my results so far:
if ( (c >= 'A') && (c <= 'Z') )
c=((c-'A'+13)%26)+'A';
if ( (c >= 'a') && (c <= 'z') )
c=((c-'a'+13)%26)+'a';
return c;
I showed this to my Prof and he said it would be possible in two lines. I don't know how i could shrink this code further and not generating wrong output.
Thanks for your help
EDIT: if nothing changed (outer range ascii) it should only return c. Maybe the solution is the second answer + return line c in case nothing returned.
You don't need to update c; just return:
if ((c >= 'A') && (c <= 'Z')) {
return ((c - 'A' + 13) % 26) + 'A';
}
if ((c >= 'a') && (c <= 'z')) {
return ((c - 'a' + 13) % 26) + 'a';
}
I also made the code more readable.
This could easily be made into two lines:
if ((c >= 'A') && (c <= 'Z')) return ((c - 'A' + 13) % 26) + 'A';
if ((c >= 'a') && (c <= 'z')) return ((c - 'a' + 13) % 26) + 'a';
Or one:
if ((c >= 'A') && (c <= 'Z')) return ((c - 'A' + 13) % 26) + 'A'; if ((c >= 'a') && (c <= 'z')) return ((c - 'a' + 13) % 26) + 'a';
But of course, that is much less readable, and not a good idea.
One line:
return (c < 'a') ? ((c - 'A' + 13) % 26) + 'A' : ((c - 'a' + 13) % 26) + 'a';
This simply makes use of the fact that lower case letters come after upper case letters in ASCII and UTF-8. Of course, it doesn't verify the input in any way.
There is a little trick using the ASCII table. Upper and lower case chars only differ one bit. So you could handle them at once. Take a look at this:
A = 0100 0001 M = 0100 1101
a = 0110 0001 m = 0110 1101
So, I think this should work:
if (Character.isLetter(c))
return (char) ((((c & 0b01011111) - 'A' + 13) % 26 + 'A') | (c & 0b00100000));
return c;
Explanation:
c & 0b01011111 turns the char into an uppercase.
- 'A' + 13 converts to an 0-based int and applies the offset.
% 26 + 'A' Take the modulo and make it back a char.
(c & 0b00100000) takes the bit that indicates wether the char was lower case or not.
| Add that bit back to the result to make it lowercase if it was.
You could use the conditional operator here to make it a one-liner:
return Character.isLetter(c) ? (char) ((((c & 0b01011111) - 'A' + 13) % 26 + 'A') | (c & 0b00100000)) : c;
After replacing the binary and char literals by decimal int literals, you get:
return Character.isLetter(c) ? (char) ((((c & 95) - 52) % 26 + 65) | (c & 32)) : c;
Eliminating spaces and some extra brackets gives: (65 chars)
return Character.isLetter(c)?(char)((((c&95)-52)%26+65)|c&32):c;
Which is a win, IMHO, if it comes to code golfing. This is of course not readable.
Demo: Yep, confirmed. It works: http://ideone.com/l6xYy6
Excerpt from the output:
= -> =
> -> >
? -> ?
# -> #
A -> N
B -> O
C -> P
D -> Q
And a bit further:
W -> J
X -> K
Y -> L
Z -> M
[ -> [
\ -> \
] -> ]
^ -> ^
_ -> _
` -> `
a -> n
b -> o
c -> p
d -> q
Slightly more correct than Sibbo's answer. This returns c as is if it falls in neither range. and in 1 line.
return ((c >= 'A') && (c <= 'Z')) ? ((c-'A'+13)%26)+'A'
:((c >= 'a') && (c <= 'z') ? ((c-'a'+13)%26)+'a'
: c);
Even shorter and (perhaps) still easier to read is
char a = c < 'a' ? 'A' : 'a';
return (c - a + 13) % 26 + a;
Note that this solution, like some of the previous answers, doesn't check the input. Moreover, in Java this code returns an int, not a char, so a cast would be necessary if the method in which it is included returns a char.
As already mentioned, I also like to stress that shortest is not necessarily best. Write readable code.
Well, if we're going for short over readable;
return (c&~32) >= 'A' && (c&~32) <= 'Z' ? ((c&31) + 12) % 26 + (c&~31) + 1 : c;
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);
}