Created
September 10, 2015 23:31
-
-
Save pkallos/60c95853b81ca47f9531 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* Problem statement: You have 25 horses, each of which run around a track at a consistent speed | |
* (i.e. running the same horse around the track yields the same speed every time). You do not | |
* have a stopwatch to time them but you are able to race them in groups around the track and | |
* rank them in order. | |
* | |
* The race track can only fit 5 horses at a time. Find the top 3 fastest horses, in the least | |
* amount of races possible. | |
*/ | |
var totalRaceCounter = 0 | |
case class Horse(label: String, speed: Double) | |
implicit class BunchaHorses(horses: List[Horse]) { | |
def race(): List[Horse] = { | |
totalRaceCounter = totalRaceCounter + 1 | |
println("Racing the following horses: ") | |
horses.foreach(h => println(" - " + h.toString)) | |
horses.sortBy(_.speed) | |
} | |
} | |
def findTopNHorses(trackSize: Int, topN: Int, horses: List[Horse]): List[Horse] = { | |
// If the track fits all the horses, | |
// just return the topN horses | |
if (trackSize >= horses.size || topN >= horses.size) { | |
horses.race().take(topN) | |
} else { | |
// Break the horses into trackSize buckets | |
val groupedHorses = horses.grouped(trackSize) | |
// Race all the horses in the groups | |
val racedHorses = groupedHorses.map(_.race).toList | |
// Label each horse group with the label of the fastest horse | |
val labeledHorseGroups = racedHorses.map { hg => | |
hg.head.label -> hg | |
}.toMap | |
// Find the TopN of these top horses (basically by racing them) | |
val topHorses = findTopNHorses(trackSize, topN, racedHorses.map(_.head)) | |
val indexedTopHorses = topHorses.zipWithIndex | |
// The potential topN fastest horses in each group is | |
// the top (groupRank - topN) horses from each group | |
val trimmedHorses = indexedTopHorses.flatMap { case(fastHorse, rank) => | |
// Taking negative returns an empty List | |
labeledHorseGroups(fastHorse.label).take(topN - rank) | |
} | |
// We already know the top horse is #1 | |
// so find the topN - 1 in the remaining pile | |
trimmedHorses.head +: findTopNHorses(trackSize, topN - 1, trimmedHorses.tail) | |
} | |
} | |
val nHorses = 25 | |
val trackSize = 5 | |
val topN = 3 | |
val horses = (1 to nHorses).map { label => | |
Horse(label.toString, util.Random.nextDouble) | |
}.toList | |
val topHorses = findTopNHorses(trackSize, topN, horses) | |
val topHorsesCheck = horses.sortBy(_.speed).take(topN).toList | |
println() | |
println(s"Racing!!") | |
println(s" Number of Horses: $nHorses") | |
println(s" Track size : $trackSize") | |
println(s" TopN : $topN") | |
println("Using limited race track: ") | |
println(topHorses) | |
println(s"Total Races: $totalRaceCounter") | |
println() | |
println("Sanity check using one race on a huge track: ") | |
println(topHorsesCheck) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment