Create a gist now

Instantly share code, notes, and snippets.

Kata Monty Hall in Scala, take two
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()
}
}
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)
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment