Created
January 19, 2014 08:49
-
-
Save sortega/8502156 to your computer and use it in GitHub Desktop.
Berlin clock kata (http://content.codersdojo.org/code-kata-catalogue/berlin-clock/) implemented in Scala when pairing with Alberto.
By just letting the tests guide the design and merciless refactoring after every step we got to this terse code.
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
package berlin | |
object BerlinClock { | |
sealed trait Light | |
case object Off extends Light | |
case object Yellow extends Light | |
case object Red extends Light | |
type Clock = List[List[Light]] | |
def format(hours: Int, mins: Int, secs: Int): Clock = for { | |
(n, lights) <- numberOfLights(hours, mins, secs) zip lightColors | |
} yield makeLightsRow(n, lights) | |
private def numberOfLights(hours: Int, mins: Int, secs: Int) = List( | |
if (secs % 4 < 2) 1 else 0, | |
hours / 5, | |
hours % 5, | |
mins / 5, | |
mins % 5 | |
) | |
private def makeLightsRow(turnedOn: Int, onLights: List[Light]) = | |
onLights.take(turnedOn) ++ List.fill(onLights.size - turnedOn)(Off) | |
private val lightColors = List( | |
List(Yellow), | |
List.fill(4)(Red), | |
List.fill(4)(Red), | |
List.tabulate(11)(index => if (index % 3 == 2) Red else Yellow), | |
List.fill(4)(Yellow) | |
) | |
} |
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
package berlin | |
import org.scalatest.FlatSpec | |
import org.scalatest.matchers.MustMatchers | |
import berlin.BerlinClock._ | |
class BerlinClockTest extends FlatSpec with MustMatchers { | |
"At 00:00:02" must "return completely off" in { | |
BerlinClock.format(0, 0, 2) must be (List( | |
List(Off), | |
List.fill(4)(Off), | |
List.fill(4)(Off), | |
List.fill(11)(Off), | |
List.fill(4)(Off) | |
)) | |
} | |
"First row's light" must "switch every two seconds" in { | |
BerlinClock.format( 0, 10, 0).head must be (List(Yellow)) | |
BerlinClock.format(12, 0, 1).head must be (List(Yellow)) | |
BerlinClock.format(23, 30, 2).head must be (List(Off)) | |
BerlinClock.format(20, 17, 8).head must be (List(Yellow)) | |
} | |
"Second row's lights" must "have a red light per 5 hours" in { | |
BerlinClock.format( 0, 10, 10)(1) must be (List.fill(4)(Off)) | |
BerlinClock.format( 6, 15, 5)(1) must be (List(Red, Off, Off, Off)) | |
BerlinClock.format(10, 0, 10)(1) must be (List(Red, Red, Off, Off)) | |
} | |
"Third row's lights" must "have a red light per hour not represented in the second row" in { | |
BerlinClock.format( 1, 10, 10)(2) must be (List(Red, Off, Off, Off)) | |
BerlinClock.format(23, 30, 59)(2) must be (List(Red, Red, Red, Off)) | |
} | |
"Forth row's lights" must "have a light on per 5 minutes" in { | |
countLightsOn(BerlinClock.format(10, 0, 10)(3)) must be (0) | |
countLightsOn(BerlinClock.format(15, 6, 5)(3)) must be (1) | |
countLightsOn(BerlinClock.format( 0, 10, 10)(3)) must be (2) | |
} | |
"Forth row's light" must "follow a repeated yellow-yellow-red pattern when turned on" in { | |
BerlinClock.format(23, 30, 10)(3) must be (List.tabulate(11)(index => { | |
if (index >= 6) Off | |
else if (index % 3 == 2) Red | |
else Yellow | |
})) | |
BerlinClock.format(23, 59, 10)(3) must | |
be (List.tabulate(11)(index => if (index % 3 == 2) Red else Yellow)) | |
} | |
"Fifth row's lights" must "have a yellow light per minute not represented in the forth row" in { | |
BerlinClock.format(23, 1, 10)(4) must be (List(Yellow, Off, Off, Off)) | |
BerlinClock.format(23, 59, 10)(4) must be (List.fill(4)(Yellow)) | |
} | |
private def countLightsOn(row: List[Light]) = row.count(_ != Off) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment