public
Last active

The Monty Hall kata in scala

  • Download Gist
Game.scala
Scala
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
import scala.util.{Random}
import scala.collection.mutable.{ListBuffer}
 
class Game(doors: ListBuffer[Symbol] = Random.shuffle(ListBuffer('Car, 'Goat, 'Goat))) {
var playerDoor:Symbol = _
var montyDoor:Symbol = _
 
if (doors.count(_ == 'Car) != 1 || doors.count(_ == 'Goat) != 2) {
throw new IllegalArgumentException("Should be one Car and two Goats")
}
 
def numberOfDoors = doors.size
def carDoor = doors.indexOf('Car)
 
def chooseDoor(doorNo: Int) = {
playerDoor = doors.remove(doorNo)
montyDoor = montyPicksDoor
}
 
def montyPicksDoor() = {
if (doors(0) == 'Goat)
doors.remove(0)
else
doors.remove(1)
}
 
def switch = playerDoor = doors.remove(0)
def playerWon = playerDoor == 'Car
override def toString = doors.mkString(", ")
}
GameSpec.scala
Scala
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65
import org.specs._
import scala.util._
import scala.collection.mutable.{ListBuffer}
 
class MontySpec extends Specification {
 
val game = new Game(ListBuffer('Goat, 'Car, 'Goat))
 
"The Game" should {
"have three doors" in {
game.numberOfDoors must_== 3
}
 
"should have one car and two doors" in {
new Game(ListBuffer('Goat, 'Goat, 'Goat)) must throwA[IllegalArgumentException]
new Game(ListBuffer('Car, 'Car, 'Car)) must throwA[IllegalArgumentException]
new Game(ListBuffer('Goat, 'Car, 'Car)) must throwA[IllegalArgumentException]
new Game(ListBuffer('Car, 'Car, 'Goat)) must throwA[IllegalArgumentException]
new Game(ListBuffer('Car, 'Goat, 'Car)) must throwA[IllegalArgumentException]
}
 
"know where the car is" in {
game.carDoor must_== 1
}
 
"be able to tell if the player was a winner" in {
game.chooseDoor(1)
game.playerWon must be(true)
}
}
 
"A Player" should {
"be able to choose a door" in {
game.chooseDoor(0)
game.playerDoor must be('Goat)
}
 
"be able to switch doors" in {
game.chooseDoor(0)
game.switch
game.playerDoor must beOneOf('Car, 'Goat)
game.numberOfDoors must_== 0
}
}
 
"Monty" should {
"pick a door after the player has chosen one" in {
game.chooseDoor(0)
game.montyDoor must be('Goat)
game.numberOfDoors must_== 1
}
}
 
"Running a thousand games" should {
"show that switching wins 2 times out of 3" in {
(for(i <- 1 to 1000) yield {
val game = new Game
game.chooseDoor(Random.nextInt(3))
game.switch
game.playerWon
}).count(_ == true) must be closeTo(667 +/- 67)
}
}
 
}

Please sign in to comment on this gist.

Something went wrong with that request. Please try again.