-3
\$\begingroup\$

A contestant is said to be a winner if his number is strictly greater than the numbers to his left and his right and a contestant is said to be a loser if his number is strictly less than the numbers to his left and right so the contestant are on a circle and I should calculate the number of winners and losers.

Please help in evaluating my solution and correcting it.

            int winner=0;
        int loser=0;
        for (int i = 0; i < contestant.length; i++) {
            if (i == 0) {
                if (contestant[0] < contestant[contestant.length - 1]
                        && contestant[0] < contestant[1])
                    loser++;
                else if (contestant[0] > contestant[contestant.length - 1]
                        && contestant[0] > contestant[1])
                    winner++;
            } else if (i == contestant.length - 1) {
                if (contestant[0] > contestant[contestant.length - 1]
                        && contestant[contestant.length - 2] > contestant[contestant.length - 1])
                    loser++;
                else if (contestant[0] < contestant[contestant.length - 1]
                        && contestant[contestant.length - 2] < contestant[contestant.length - 1])
                    winner++;
            } else {
                if (contestant[i] < contestant[i + 1] &&contestant[i] < contestant[i - 1])
                    loser++;
                else if (contestant[i] > contestant[i + 1]
                        && contestant[i] > contestant[i - 1])
                    winner++;
            }
        }
\$\endgroup\$

closed as unclear what you're asking by IEatBagels, 200_success Apr 15 '15 at 5:48

Please clarify your specific problem or add additional details to highlight exactly what you need. As it's currently written, it’s hard to tell exactly what you're asking. See the How to Ask page for help clarifying this question. If this question can be reworded to fit the rules in the help center, please edit the question.

  • 1
    \$\begingroup\$ CodeReview is about reviewing the complete code. \$\endgroup\$ – Shirishkumar Bari Apr 10 '15 at 12:35
  • 1
    \$\begingroup\$ @Shree has a point - your code is not complete. There is enough to review, but it would make for a much better question if you could, for example, make it easy to run, give an example, or something. \$\endgroup\$ – rolfl Apr 10 '15 at 12:38
  • \$\begingroup\$ It looks like nothing but embedding in a method is missing. But you should also add a main method calling it so we can try it out. It's not much work but it helps a lot. \$\endgroup\$ – maaartinus Apr 10 '15 at 12:42
1
\$\begingroup\$

One problem with your method is that you didn't write any. Maybe because you'd need to return both winner and loser from it. Returning two things is impossible, but you can always write a class encapsulating them. I did it below and let its constructor do the whole computation.

Another problem is that the code is far too long. Maybe you're handling the border cases correctly, maybe you're not, it's too much (similarly looking) code to read.

A simple trick for handling circles is to compute the indexes in a circular manner instead of repeating the lengthy expression again and again. Another trick would be to define a method `isWinner(current, next, previous).

The code is also long because of the lengthy identifier contestant. Normally, I'd define a local variable and use it instead in order to keep the lines short.

You've forgot a space in &&contestant and your algorithm for breaking lines is a bit inconsistent. But these are very minor issues.

class Contestanter {
    private int winner;
    private int loser;

    Contestanter(int contestant) {
        int length = contestant.length;
        for (int i = 0; i < length; i++) {
            int next = i == length - 1 ? 0 : i + 1;
            int prev = i == 0 ? length - 1 : i - 1;
            if (contestant[i] < contestant[next] && contestant[i] < contestant[prev]) {
                loser++;
            } else if (contestant[i] > contestant[next] && contestant[i] > contestant[prev]) {
                winner++;
            }

    int getWinner() {
         return winner;
    }

    int getLoser() {
         return loser;
    }
}
\$\endgroup\$
1
\$\begingroup\$

There are two tricks you should be aware of when challenged with problems like this.

  • The first is that you should be identifying changes in direction: inflection points.
  • The second is that there are three states you are trying to identify: an entry is larger, the same, or smaller than the previous entry.

When scanning the data, you can calculate the 'direction' of a point, and then reuse that direction for the next test as well.

Java has a 'compareTo(...)' concept which returns a positive value if the first comared value is larger than the second. It returns a negative value if the first value is less than the second. It returns 0 if they are the same. For integer values, this is easy to do with: Integer.compare(int, int).

Using that, we can simply do:

current = Integer.compare(contestant[i+1], contestant[i]);

The value in current will be positive, 0, or negative if the i+1 value is larger, the same as, or less than the i value.

Now, if we have done the same with the i and i - 1 values (stored in previous), we can use some math-tricks to help:

  • anything multiplied by 0 is 0.
  • two positives multiplied is a positive.
  • two negatives multiplied is a positive.
  • a positive and negative multiplied is a negative.

i.e. if we multiply the previous and current, and the result is negative, then we have a peak, or trough (an inflection).

If current is positive, then the inflection is a low-point. If current is negative, then the inflection is a high point.

Using them all together, the code:

    int wincount = 0;
    int losecount = 0;
    if (contestants.length > 1) {
        int current = Integer.compare(contestants[0], contestants[contestants.length - 1]);
        for (int i = 0; i < contestants.length; i++) {
            int previous = current;
            current = Integer.compare(contestants[(i + 1) % contestants.length], contestants[i]);
            if (current * previous < 0) {
                if (current > 0) {
                    losecount++;
                } else {
                    wincount++;
                }
            }
        }
    }

I have put this in to an ideone here too;

\$\endgroup\$
  • \$\begingroup\$ You were 17 seconds faster... nice trick with the inflection points. For length==2 there should be IMHO wincount = losecount = contestants[0] != contestants[1] ? 1 : 0, shouldn't it? \$\endgroup\$ – maaartinus Apr 10 '15 at 13:06
  • \$\begingroup\$ I was working on the wrap-around immediately after I posted, @maaartinus - was the 'circular' part of the original question, or was it an in-the-grace-period edit? - the ideone is fixed too now. \$\endgroup\$ – rolfl Apr 10 '15 at 13:09
  • \$\begingroup\$ Not sure, if I understand: I guess, the OP has never edited it. And the circularity is the only reason for such a complicated code. Otherwise they could simply forget the first and last elements. \$\endgroup\$ – maaartinus Apr 10 '15 at 13:14
  • \$\begingroup\$ @maaartinus - edits made in the first 5 minutes of posting something do not show up in the edit history... I was just wondering whether the 'circular' nature of the problem was added in that 5 minutes, or whether I just did not see it until after I posted my answer... that's all. \$\endgroup\$ – rolfl Apr 10 '15 at 13:16

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