HiveBrain v1.2.0
Get Started
← Back to all entries
patternMinor

Finding the Greatest Integer and Ties

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
thegreatesttiesfindingandinteger

Problem

I'm trying to find the greatest integer of four integers and its ties. I used the following code. Is there anyway to simplify this?

int winner = MAX(self.playerOneScore, MAX(self.playerTwoScore, MAX(self.playerThreeScore, self.playerFourScore)));

if (winner == self.playerOneScore && winner != self.playerTwoScore && winner != self.playerThreeScore  && winner != self.playerFourScore) {
    NSLog(@"1");
} else if (winner == self.playerTwoScore && winner != self.playerOneScore && winner != self.playerThreeScore && winner != self.playerFourScore) {
    NSLog(@"2");
} else if (winner == self.playerThreeScore && winner != self.playerOneScore && winner != self.playerTwoScore && winner != self.playerFourScore) {
    NSLog(@"3");
} else if (winner == self.playerFourScore && winner != self.playerOneScore && winner != self.playerTwoScore && winner != self.playerThreeScore) {
    NSLog(@"4");
} else if (self.playerOneScore == self.playerTwoScore || self.playerOneScore ==  self.playerThreeScore || self.playerOneScore == self.playerFourScore || self.playerTwoScore == self.playerThreeScore || self.playerTwoScore == self.playerFourScore || self.playerThreeScore == self.playerFourScore) {
    NSLog(@"Tie");
}

Solution

Your code looks correct (apart from the typo in case #4). Note that the final else if is not necessary.
If none of the first 4 tests passes then you necessarily have a tie,
so a simple else is sufficient here.

The winner variable is named badly, as it contains the maximal score and
not the winning player.

But you are using far too many comparisons, and the code does not scale well for a larger number of players. What you need to know is

  • Which player has the maximum score?



  • How many players have the maximum score?



Both can more easily determined if all scores are stored in an array.

Since you
are working with Objective-C, I would suggest to take advantage of the
classes and methods that the Foundation framework provides.

First create an NSArray of all player scores. Objective-C collections can only
contain objects, therefore the integers have to be boxed into NSNumber
with @(...):

NSArray *scores = @[@(score1), @(score2), @(score3), @(score4)];


Use Key-Value Coding to find the maximum element:

NSNumber *maxScore = [scores valueForKeyPath:@"@max.self"];
NSLog(@"maximum score is %@", maxScore);


Use indexesOfObjectsPassingTest: to find all objects in the scores array
that are equal to the maximum score:

NSIndexSet *bestPlayers = [scores indexesOfObjectsPassingTest:^BOOL(NSNumber *obj, NSUInteger idx, BOOL *stop) {
    return [obj isEqual:maxScore];
}];


If the index set has only one element then there is a unique winner, otherwise a tie:

if ([bestPlayers count] == 1) {
    NSLog(@"Best player is #%ld", [bestPlayers firstIndex] + 1);
} else {
    NSLog(@"Tie between");
    [bestPlayers enumerateIndexesUsingBlock:^(NSUInteger idx, BOOL *stop) {
        NSLog(@"  Player #%ld", idx + 1);
    }];
}


(Array indices are 0-based, therefore you add one to get the player number.)

Code Snippets

NSArray *scores = @[@(score1), @(score2), @(score3), @(score4)];
NSNumber *maxScore = [scores valueForKeyPath:@"@max.self"];
NSLog(@"maximum score is %@", maxScore);
NSIndexSet *bestPlayers = [scores indexesOfObjectsPassingTest:^BOOL(NSNumber *obj, NSUInteger idx, BOOL *stop) {
    return [obj isEqual:maxScore];
}];
if ([bestPlayers count] == 1) {
    NSLog(@"Best player is #%ld", [bestPlayers firstIndex] + 1);
} else {
    NSLog(@"Tie between");
    [bestPlayers enumerateIndexesUsingBlock:^(NSUInteger idx, BOOL *stop) {
        NSLog(@"  Player #%ld", idx + 1);
    }];
}

Context

StackExchange Code Review Q#68004, answer score: 6

Revisions (0)

No revisions yet.