public
Last active

Kata Monty Hall in Scala, take two

  • 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 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52
import scala.util.Random
import scala.collection.mutable.ListBuffer
 
abstract class Door
case class Car() extends Door
case class Goat() extends Door
 
class Game(val doors:List[Door] = Random.shuffle(List(Goat(), Goat(), Car()))) {
var playerDoor = -1
var montyDoor = -1
var monty = new Monty(this)
def chooseDoor(door: Int) = {
playerDoor = door
montyDoor = monty.pickDoor()
}
 
def switch() = {
playerDoor = {
val availableDoors = ListBuffer(0, 1, 2)
availableDoors -= playerDoor
availableDoors -= montyDoor
availableDoors.head
}
}
 
def won() = {
doors(playerDoor) == Car()
}
}
 
class Player(game: Game) {
def chooseDoor(door: Int) = {
game.chooseDoor(door)
}
 
def switch() = {
game.switch()
}
}
 
class Monty(game: Game) {
def pickDoor():Int = {
val availableDoors = ListBuffer(0, 1, 2)
availableDoors -= game.playerDoor
val montyPick = availableDoors(Random.nextInt(2))
if (game.doors(montyPick) != Car())
montyPick
else
pickDoor()
}
}
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 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81
import org.specs._
import org.specs.mock.Mockito
import org.mockito.Matchers._
import scala.util._
import scala.collection.mutable.{ListBuffer}
 
class MontySpec extends Specification with Mockito {
 
val game = new Game(List(Goat(), Goat(), Car()))
val player = new Player(game)
 
"The Game" should {
 
"have two Goats and a Car" in {
game.doors.size must_== 3
game.doors.filter{_.isInstanceOf[Car]}.size must_== 1
game.doors.filter{_.isInstanceOf[Goat]}.size must_== 2
}
 
"make Monty select a door after the player has choosen one" in {
player.chooseDoor(0)
game.montyDoor must_!= -1
}
 
"make Monty choose another door than the player" in {
player.chooseDoor(0)
game.montyDoor must_!= game.playerDoor
}
 
"make Monty choose a door that is not a Car" in {
player.chooseDoor(0)
game.doors(game.montyDoor) must_!= Car()
}
 
"make sure Montys door choosing is not the same all the time" in {
val game = new Game(List(Goat(), Car(), Goat()))
val player = new Player(game)
player.chooseDoor(1)
game.montyDoor must_!= game.playerDoor
}
 
"know that the player lost if he chooses a Goat" in {
player.chooseDoor(0)
game.won() must_== false
}
 
"know that the player won if he chooses the Car" in {
player.chooseDoor(2)
game.won must_== true
}
 
}
 
"The Player" should {
 
"be able to select a door" in {
player.chooseDoor(0)
game.playerDoor must_== 0
}
 
"be able to switch door after Monty has picked a door" in {
player.chooseDoor(0)
player.switch()
game.playerDoor must_!= 0
}
}
 
"A simulation" should {
"show that switching will win two times out of three" in {
val thousandGames = for(i <- 1 to 1000) yield {
val game = new Game
val player = new Player(game)
player.chooseDoor(0)
player.switch()
game.won()
}
thousandGames.count(_ == true) must be closeTo(667 +/- 67)
}
}
}

Please sign in to comment on this gist.

Something went wrong with that request. Please try again.