Created
December 30, 2010 23:49
-
-
Save jorgen99/760496 to your computer and use it in GitHub Desktop.
Kata Monty Hall in Scala, take two
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
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() | |
} | |
} |
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
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