Skip to content

Instantly share code, notes, and snippets.

@shikhar
Created January 17, 2011 00:27
Show Gist options
  • Save shikhar/782299 to your computer and use it in GitHub Desktop.
Save shikhar/782299 to your computer and use it in GitHub Desktop.
object TenPinBowling {
/**
* Returns the score for each frame of a 10-pin bowling game.
*
* @param rolls
* List of pins knocked down by each roll
* @return
* List of scores for each frame
*/
def score(rolls: List[Int]): List[Int] = {
def badInput() = { throw new IllegalArgumentException("Bad input") }
def calculate(rolls: List[Int], frame: Int, pastScores: List[Int]): List[Int] = {
val lastScore = if (pastScores.isEmpty) 0 else pastScores.head
val (frameScore, extraBallsCounted, rest) = rolls match {
case 10 :: a :: b :: xs => // Strike
(10 + a + b + lastScore, 2, a :: b :: xs)
case a :: b :: c :: xs if a + b == 10 => // Spare
(10 + c + lastScore, 1, c :: xs)
case a :: b :: xs if a + b < 10 => // Normal 2-roll frame
(a + b + lastScore, 0, xs)
case _ =>
badInput()
}
if (frame == 10)
// Any balls left should be accounted for by a strike or spare
if (rest.length == extraBallsCounted)
frameScore :: pastScores
else
badInput()
else
calculate(rest, frame + 1, frameScore :: pastScores)
}
if (rolls.exists(x => x < 0 || x > 10))
badInput()
else
calculate(rolls, 1, Nil).reverse
}
def main(args: Array[String]): Unit = {
if (args.length < 10 || args.length > 21) {
println("Specify the rolls as arguments, "
+ "e.g. for the perfect game 10 10 10 10 10 10 10 10 10 10 10 10")
exit(1)
}
val rolls = args.map(_.toInt).toList
println("Scores: " + score(rolls))
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment