Teacher wants only one if for 3 [(a OR b) AND c] questions - java-io

This is a weird question, I know, but I need to write a program with 3 questions basically [(a OR b) AND c] without using if. What my teacher wants us to ask the user if an animal is black and answer y or n. If n ask if it is white and answer y or n. If either statement is true, then ask if it is friendly, answering y or n. If it is black or white and friendly then we get a message that it can come home with me or else we get a sorry message My problem is that she says we can use only one if and must use compareToIgnoreCase and a function. I can do this with if, but I can't figure out even how to begin without using if. Please help, I've Googled, read all kinds of answers to anything sounding at all promising, and all I keep finding directs me to use if statements.

This seems like a question to teach you short-circuit evaluation. The idea is to have function answersYesTo(String question) and use that in your boolean expression (a || b) && c. Short-circuit evaluation will start with evaluating a and only evaluate b if a evalutes to false. The reason for this is that if a is true, then the we already know that a||b is true, so there is no need to evalute the last part of the subexpression.
Furthermore, c will NOT be evaluated if a||b evalutes to false, since we at that point know that the expression will evalute to false.
The following code shows one possible implementation:
import java.io.Console;
public class App
{
static public void main(String [] args) {
boolean allowedToBringHome =
(answersYesTo("Is the animal black?")||answersYesTo("Is the animal white?"))
&& answersYesTo("Is it friendly?");
if( allowedToBringHome ) {
print("You can bring the animal home.");
}
else {
print("Sorry, you can't bring the animal home.");
}
}
static boolean answersYesTo(String question) {
String answer = System.console().readLine(question);
return answer.compareToIgnoreCase("y")==0;
}
static void print(String msg) {
System.out.println(msg);
}
}
NOTE: When using short-circuit evaluation always consider readbility of your code. Complex expressions become difficult to read and grasp very quickly, which increases the risk of introducing bugs.

You can try using the ternary operator (http://en.wikipedia.org/wiki/%3F:)
You not using the actual "if" operator, but instead an if/else.
Example:
if (a == b)
return 1; else
return 0;
is the same as
return (a == b) ? 1 : 0

I don't think we're going to do your homework for you, but depending on your teacher's definition of using an 'if', you may be able to use a ternary operator.
i.e. you can write if (A) do x else do y as A ? x : y.
Alternatively, read up on switch/case statements. This isn't a great solution for this sort of thing but does work with your constraints.

Related

Inline if with else

I realize that it's not valid ruby but what would be the technical hurdles to implement the below functionality into the Ruby core language (of say v2.3)?
variable = 1 if condition else -1
I'd also like to allow the following for more generic use.
variable = { 1 } if condition else { -1 }
I'm very open to requiring an "end" at the end.
I get that a ternary can easily accomplish this but I'm looking for a more readable inline-if that allows an else.
I get that I can make a function which does this via any number of styles but I'd prefer to have it as readable as possible.
Thanks.
EDIT: I hate editing questions for obvious reasons.
In response to the question of how the generic option is more ruby-esque, see the below example (I needed newlines).
variable = {
operation_one
operation_two
...
SUCCESS_STATUS_CODE
} if loaded_dependencies else {
do_detailed_logging
FAILURE_STATUS_CODE
}
if variable then
it_worked
else
explain_why
end
Because your example, while it seems readable to you, has too many ambiguities in other cases.
Not to mention that ruby has a way to do this, and it's the ternary operator. To say that your example is more ruby-like, is almost like wondering why the wheelbase of the Ford Mustang wasn't longer, and that it would be more "Mustang-like" if it was.
But here are some issues with your proposal, starting from your example:
variable = { 1 } if condition else { -1 }
Here you've given your "if else" bit a lower precedence than the "=".
In other words:
variable = ({ 1 } if condition else { -1 })
That's a serious problem, because it breaks the currently allowed:
variable = 1 if condition
The precedence for that statement is:
(variable = 1) if condition
And that's important. No assignment happens if the condition is false.
This can be a really big deal, for example if the lvalue (left side) actually has side-effects. For example:
var[0] = 1 if condition
The lookup for "var[0]" is a method in whatever class object var is, and while [] doesn't usually have side-effects, it can - and now you are going to do those side effects even if the condition is false.
And I won't even get into:
variable = { 1 } if condition if condition2 else { -1 }
But if you don't like it, you can always write your own language and see what happens!

Compound Boolean Expr: Void Value Expression

def success?
return #fhosts.empty? and #khosts.empty? and #shosts.any?
end
When I run that instance method, I get an error:
/home/fandingo/code/management/lib/ht.rb:37: void value expression
return #fhosts.empty? and #khosts.empty? and #shosts.any?
I'm confused by what's happening since this works
def success?
#fhosts.empty? and #khosts.empty? and #shosts.any?
# This also works
# r = #fhosts.empty? and #khosts.empty? and #shosts.any?
# return r
end
I'm coming from a Python background, and I don't want anything to do with implicit returns. Programming has plenty of landmines as it is.
If we have an arbitrary expression, E, that consists of boolean operations and and or together, here are some operations we could perform:
if E -- works
E -- works
* v = E -- works
return E -- broken
Why doesn't the last case work?
Edit: Actually v = E doesn't work. Only
v = Ei
is evaluated. Ei+1...k are ignored.
This is likely due to the very weak binding of and which causes it to parse out differently than you expect:
return x and y
This actually means:
(return x) and y
Since you're returning immediately it doesn't have a chance to evaluate the remainder of the expression.
Your version without return is correct:
x and y
This doesn't have a binding issue and is more idiomatic Ruby. Remember you only need to put an explicit return if you're trying to force an exit before the last line of the method. Being opposed to implicit returns is going to make your code look heavily non-Ruby. They're one of the reasons Ruby is so clean and simple, and how things like a.map { |v| v * 2 } works.
The When in Rome principle applies here. If you want to write Python-style Ruby you're going to be going against the grain. It's like saying "I don't like how you say X in your spoken language, so I'll just ignore that and do it my way."
This should also work:
return x && y
The && method is very strongly bound so return is the last thing evaluated here.
Or if you really want to use and for whatever reason:
return (x and y)

What's the difference between if(A) then if(B) and if (A and B)?

if(A) then if(B)
vs
if(A and B)
Which is better to use and why ?
Given:
if (a) {
if (b) {
/// E1
}
/// E2
} else {
// E3
}
One may be tempted to replace it with:
if (a && b) {
/// E1
} else {
// E3
}
but they are not equivalent(a = true and b = false shows the counter-argument for it)
Other than that, there is no reason not to chain them if the language allows short circuits operations like AND, OR. And most of them allows it. Expressions are equivalent and you can use the chained form to improve code readability.
It depends on your specific case but generally:
1) if (A and B) looks better/cleaner. It's immediately clear that the following block will execute if both A and B apply.
2) if(A) then if(B) is better in cases when you want to do something also when A applies, but B doesn't. In other words:
if (A):
if (B):
# something
else:
# something else
generally looks better than
if (A and B):
# something
if (A and not B):
# something else
You've tagged this 'algorithm' and 'logic' and from that perspective I would say little difference.
However in practical programming languages there may or may not be a question of efficiency (or even executability).
Programming languages like C, C++ and Java guarantee that in the expression A && B that A is evaluated first and if false B is not evaluated.
That can make a big difference if B is compuatationally expensive or is invalid if A is false.
Consider the following C snippet:
int*x
//....
if(x!=NULL&&(*x)>10) {
//...
Evaluating (*x) when x==NULL will very likely cause a fatal error.
This 'trick' (called short-circuit evaluation) is useful because it avoids the need to write the slightly more verbose:
if(x!=NULL){
if((*x)>10){
Older versions of VB such as VB6 are infamous for not making the short circuits.
The other one is that B in A || B will not be evaluated if A is true.
Discussion about support:
Do all programming languages have boolean short-circuit evaluation?
In any language that provides short-circuit and has an optimizing compiler you can assume there is unlikely to be any difference in code efficiency and go with the most readable.
That is normally if(A&&B).

Concise notation for assigning `unique_ptr`?

I have a pointer to a parent class and I want to assign a new child object to that pointer conditionally. Right now, the syntax I have is rather lengthly:
std::unique_ptr<ParentClass> parentPtr;
if (...) {
parentPtr = std::unique_ptr<ParentClass>(new ChildClass1());
} else {
parentPtr = std::unique_ptr<ParentClass>(new ChildClass2());
}
Is there a good way of making this more readable / less lengthly?
Two possibilities would be:
std::unique_ptr<ParentClass> parentPtr(condition ?
(ParentClass*)new ChildClass1() :
(ParentClass*)new ChildClass2());
If condition is complicated, just assign a boolean to it and then write the construction. This solution only works for a binary condition though.
Another is to embrace C++14, and use
parentPtr = std::make_unique<ChildClass>();
First off, the "obvious" solution C ? new X : new Y does not work, since even if X and Y have a common base class A, the types X * and Y * have no common type. This is actually not so surprising after all if you consider that a class can have many bases (direct or indirect) and a given type may appear as a base multiple times.
You could make the conditional operator work by inserting a cast:
A * = C ? static_cast<A *>(new X) : static_cast<A *>(new Y);
But this would quickly get long and tedious to read when you try to apply this to your real situation.
However, as for std::unique_ptr, it offers the reset function which can be used to good effect here:
std::unique_ptr<A> p;
if (C)
{
p.reset(new X);
}
else
{
p.reset(new Y);
}
Now even if the actual new expressions are long, this is still nicely readable.

Early return statements and cyclomatic complexity

I prefer this writing style with early returns:
public static Type classify(int a, int b, int c) {
if (!isTriangle(a, b, c)) {
return Type.INVALID;
}
if (a == b && b == c) {
return Type.EQUILATERAL;
}
if (b == c || a == b || c == a) {
return Type.ISOSCELES;
}
return Type.SCALENE;
}
Unfortunately, every return statement increases the cyclomatic complexity metric calculated by Sonar. Consider this alternative:
public static Type classify(int a, int b, int c) {
final Type result;
if (!isTriangle(a, b, c)) {
result = Type.INVALID;
} else if (a == b && b == c) {
result = Type.EQUILATERAL;
} else if (b == c || a == b || c == a) {
result = Type.ISOSCELES;
} else {
result = Type.SCALENE;
}
return result;
}
The cyclomatic complexity of this latter approach reported by Sonar is lower than the first, by 3. I have been told that this might be the result of a wrong implementation of the CC metrics. Or is Sonar correct, and this is really better? These related questions seem to disagree with that:
https://softwareengineering.stackexchange.com/questions/118703/where-did-the-notion-of-one-return-only-come-from
https://softwareengineering.stackexchange.com/questions/18454/should-i-return-from-a-function-early-or-use-an-if-statement
If I add support for a few more triangle types, the return statements will add up to make a significant difference in the metric and cause a Sonar violation. I don't want to stick a // NOSONAR on the method, as that might mask other problems by new features/bugs added to the method in the future. So I use the second version, even though I don't really like it. Is there a better way to handle the situation?
Your question relates to https://jira.codehaus.org/browse/SONAR-4857. For the time being all SonarQube analysers are mixing the cyclomatic complexity and essential complexity. From a theoretical point of view return statement should not increment the cc and this change is going to happen in the SQ ecosystem.
Not really an answer, but way too long for a comment.
This SONAR rule seems to be thoroughly broken. You could rewrite
b == c || a == b || c == a
as
b == c | a == b | c == a
and gain two points in this strange game (and maybe even some speed as branching is expensive; but this is on the discretion of the JITc, anyway).
The old rule claims, that the cyclomatic complexity is related to the number of tests. The new one doesn't, and that's a good thing as obviously the number of meaningfull tests for your both snippets is exactly the same.
Is there a better way to handle the situation?
Actually, I do have an answer: For each early return use | instead of || once. :D
Now seriously: There is a bug requesting annotations allowing to disable a single rule, which is marked as fixed. I din't look any further.
Since the question is also about early return statements as a coding style, it would be helpful to consider the effect of size on the return style. If the method or function is small, less than say 30 lines, early returns are no problem, because anyone reading the code can see the whole method at a glance including all of the returns. In larger methods or functions, an early return can be a trap unintentionally set for the reader. If the early return occurs above the code the reader is looking at, and the reader doesn't know the return is above or forgets that it is above, the reader will misunderstand the code. Production code can be too big to fit on one screen.
So whoever is managing a code base for complexity should be allowing for method size in cases where the complexity appears to be problem. If the code takes more than one screen, a more pedantic return style may be justified. If the method or function is small, don't worry about it.
(I use Sonar and have experienced this same issue.)

Resources