Skip to content

Instantly share code, notes, and snippets.

@kings13y
Created March 23, 2011 16:35
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save kings13y/883407 to your computer and use it in GitHub Desktop.
Save kings13y/883407 to your computer and use it in GitHub Desktop.
Sample solution to standard bowling kata (http://codingdojo.org/cgi-bin/wiki.pl?KataBowling) using Scala pattern matching and extractors
// Idiomatic solution using extrators
// Extractors allow us to bind parameters to an object and are usable in pattern matches to see if a pattern can apply to the params submitted.
// Note this is simialr to case classes, but works against an Object (which are like 'static' classes in Java). Also it incurs some performance penalties
// as opposed to using case classes
class BowlingForExtractors() {
def score(bowls:List[Int]) = scoreFrames(bowls).slice(0,10).sum // take the first 10 elements from the List and sum them..any additional elements are the result of additional strikes
def scoreFrames(bowls:List[Int]) : List[Int] = bowls match {
case Nil => List(0)
case isStrike() =>
bowls.slice(0,3).sum :: scoreFrames(bowls drop 1) // :: is the cons operator and is right associative. Basically it prepends
case isSpare() =>
bowls.slice(0,3).sum :: scoreFrames(bowls drop 2) // elements to the left to the start of a List. the drop 'infix' operator
case _ =>
bowls.slice(0,2).sum :: scoreFrames(bowls drop 2) // removes the named number of elements from the start of the List
}
object isStrike { // typical extractors would implement an apply method for creating an object instance based on params passed in..
def unapply(bowls:List[Int]) = bowls match {
case 10::_ => true
case _ => false
}
}
object isSpare {
def unapply(bowls:List[Int]) = bowls match {
case a::b::_ if a+b == 10 => true
case _ => false
}
}
}
object BowlingKataRunner {
val allFoursAndFives = List(4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5) // Should == 90
val allFives = List(5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5) // Should == 150
val allStrikes = List(10,10,10,10,10,10,10,10,10,10,10,10) // Should == 300
def main(args: Array[String]) {
val extractorSolution = new BowlingForExtractors()
println("Testing Bowling using extractors....")
println("4s and 5s: " + ((extractorSolution score allFoursAndFives) == 90))
println("All 5s: " + ((extractorSolution score allFives) == 150) )
println("All Strikes: " + ((extractorSolution score allStrikes) == 300) )
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment