patternMinor
Finding the Greatest Integer and Ties
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
If none of the first 4 tests passes then you necessarily have a tie,
so a simple
The
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
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
contain objects, therefore the integers have to be boxed into
with
Use Key-Value Coding to find the maximum element:
Use
that are equal to the maximum score:
If the index set has only one element then there is a unique winner, otherwise a tie:
(Array indices are 0-based, therefore you add one to get the player number.)
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 andnot 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 onlycontain objects, therefore the integers have to be boxed into
NSNumberwith
@(...):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 arraythat 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.