2
\$\begingroup\$

Problem Statement

Given an integer N, perform the following conditional actions:

  • If N is odd, print Weird
  • If N is even and in the inclusive range of 2 to 5, print Not Weird
  • If N is even and in the inclusive range of 6 to 20, print Weird
  • If N is even and greater than 20, print Not Weird

Complete the stub code provided in your editor to print whether or not N is weird.

Input Format: A single line containing a positive integer, N.

Constraints: 1<=N<=100

Output Format: Print Weird if the number is weird; otherwise, print Not Weird.

My Solution

if(N%2!=0)
    System.out.println("Weird");
else{
            if(N>=2&&N<=5||N>20)
            System.out.println("Not Weird");
            else
            System.out.println("Weird");
        }

Another Solution-

if(N%2==1)
            System.out.println("Weird");
        else
            {
            if(N>=2&&N<=5)
                System.out.println("Not Weird");
            else if(N<=20)
                System.out.println("Weird");
                else
                System.out.println("Not Weird");
        }

My question is, does one algorithm have better performance than the other, in other words, is there any advantage to using else if statements rather than logical operators.

P.S- I am new to coding in Java, and was just curious if there is an optimum way to write code that has better performance.

\$\endgroup\$
1
  • 1
    \$\begingroup\$ "does one algorithm have better performance than the other" No, any decent compiler would emit the same byte code for that. \$\endgroup\$ Sep 27, 2019 at 17:01

3 Answers 3

3
\$\begingroup\$

In addition to the things dfhwze already mentioned:

  1. You should separate calculation and output. Even the shorter solution mentioned by dfhwze contains a repetition of the output code (System.out.println) and the output message ("Not weird"). Furthermore, thinking on to real world problems, code that only outputs something is really hard to unit-test.

Thus, do something like:

private static boolean isWeird(int n) {
   return (n % 2 != 0) || (n >= 6 && n <= 20); // or however you want to do the calculation
}

... // and in main:
boolean weird = isWeird(n);
if (weird) {
   System.out.println("Weird");
}
else {
   System.out.println("Not Weird");
}
  1. One missing convention: variables should start with a lowecase character: N should be renamed to n
\$\endgroup\$
2
\$\begingroup\$

As stated in the comments, this flow is simple enough for a compiler to optimize the code. So I wouldn't bother comparing performance between both methods. I would focus on readability and coding guidelines.

Conventions

You have customized formatting to somewhat align the System.out.println statements. While I consider this a form of art, it hurts readability. Keeping conventions in mind:

  • A keyword followed by a parenthesis should be separated by a space.
  • A blank space should not be used between a method name and its opening parenthesis.
  • All binary operators except . should be separated from their operands by spaces.
  • Be consistent in indentation size. Let's pick 4 characters.
  • And a good reason to prefer including curly braces for if-statements.

Solution 1

if (N % 2 != 0) {
    System.out.println("Weird");
}
else {
    if (N >=2 && N <= 5 || N > 20) {
        System.out.println("Not Weird");
    }
    else {
        System.out.println("Weird");
    }
}

Solution 2

if (N % 2 == 1) {
    System.out.println("Weird");
}
else {
    if (N >= 2 && N <= 5) {
        System.out.println("Not Weird");
    }
    else if (N <= 20) {
        System.out.println("Weird");
    }
    else {
        System.out.println("Not Weird");
    }
}

Other formatting options might include using the ternary operator or combining conditions to only print each outcome once. I leave it up to you as an exercise to try these out.

\$\endgroup\$
2
\$\begingroup\$

Since you asked, I wouldn't think there would be any difference between using else vs ||.

But, related to that, and to add on to the other answers, is that code should normally be written for humans first, and only incidentally for computers.

It takes only a bit of mental effort to reason that (n % 2 != 0) || (n >= 6 && n <= 20) fulfils the four bullet points given, but it's even easier to mentally verify that this code does, because it exactly mirrors the problem statement:

public static boolean isWierd(int n) {

    if (n % 2 == 1) {
        return true;
    }

    if (2 <= n && n <= 5) {
        return false;
    }

    if (6 <= n && n <= 20) {
        return true;
    }

    return false;

}

When somebody is hunting through thousands of lines to find where a bug enters the system, it might be that they're having to keep in their minds the state of a number of variables and the call stack, potentially for several different execution paths. It should be as simple as possible for them to look at the isWierd function, convince themselves that it is correct, and move on.

And as with the other answers, the performance difference at this scale is likely to be either optimized away or be too small to matter (you can always come back to this if it does end up mattering).

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.