Permalink
Browse files

Bowling kata

  • Loading branch information...
0 parents commit 6dc4950874b4927a74a690e92c3f6dfdd30f0588 @citizen428 committed Feb 16, 2012
Showing with 91 additions and 0 deletions.
  1. +3 −0 .gitignore
  2. +11 −0 bowling/build.sbt
  3. +34 −0 bowling/src/main/scala/bowling.scala
  4. +43 −0 bowling/src/test/scala/BowlingSpec.scala
@@ -0,0 +1,3 @@
+target
+.idea
+.idea_modules
@@ -0,0 +1,11 @@
+name := "bowling"
+
+version := "1.0"
+
+scalaVersion := "2.9.1"
+
+libraryDependencies ++= Seq(
+ "org.specs2" %% "specs2" % "1.8")
+
+resolvers ++= Seq("snapshots" at "http://oss.sonatype.org/content/repositories/snapshots",
+ "releases" at "http://oss.sonatype.org/content/repositories/releases")
@@ -0,0 +1,34 @@
+object Bowling {
+ private def scoreValue(score: Char): Int = {
+ score match {
+ case 'x' => 10
+ case '-' => 0
+ case digit => digit.toString.toInt
+ }
+ }
+
+ private def scoreFrames(frames: List[Char]): List[Int] = {
+ frames match {
+ case Nil => List()
+ case 'x' :: _ :: '/' :: _ =>
+ 20 :: scoreFrames(frames.drop(1)) // strike + spare == 20
+ case 'x' :: _ =>
+ frames.take(3).map(scoreValue).sum :: scoreFrames(frames.drop(1))
+ case _ :: '/' :: nextRoll :: _ =>
+ (10 + scoreValue(nextRoll)) :: scoreFrames(frames.drop(2))
+ case _ =>
+ frames.take(2).map(scoreValue).sum :: scoreFrames(frames.drop(2))
+ }
+ }
+
+ def score(scores: String): Int = {
+ assert(scores.matches("[0-9x/-]{10,22}"), "Invalid scores!")
+ scoreFrames(scores.toList).take(10).sum // don't count bonus frames as normal frames
+ }
+
+ def main(args: Array[String]): Unit = {
+ print("Enter frame scores: ")
+ val result = score(readLine())
+ println("Total score: " + result)
+ }
+}
@@ -0,0 +1,43 @@
+import org.specs2.mutable._
+
+class BowlingSpec extends Specification {
+ "For an open frame it" should {
+ "add the points of the two rolls" in {
+ Bowling.score("11--------") must_== 2
+ }
+ }
+
+ "For a spare it" should {
+ "award the next frame as bonus" in {
+ Bowling.score("9/3-------") must_== 16
+ }
+ }
+
+ "For a strike it" should {
+ "award the next 2 frames as bonus" in {
+ Bowling.score("x34-------") must_== 24
+ }
+ }
+ "For an entire game it" should {
+ "score a perfect game with 300" in {
+ Bowling.score("xxxxxxxxxxxx") must_== 300
+ }
+
+ "give 0 points for all in gutter" in {
+ Bowling.score("----------") must_== 0
+ }
+
+ "score a game of 9s with 90" in {
+ Bowling.score("9-9-9-9-9-9-9-9-9-9-") must_== 90
+ }
+
+ "score a game of 5-spares with 150" in {
+ Bowling.score("5/5/5/5/5/5/5/5/5/5/5") must_== 150
+ }
+ "score an average game with 168" in {
+ Bowling.score("x7/729/xxx236/7/3") must_== 168
+ }
+ }
+}
+
+

0 comments on commit 6dc4950

Please sign in to comment.