Skip to content

Instantly share code, notes, and snippets.

@seratch
Created March 31, 2012 00:55
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save seratch/2258356 to your computer and use it in GitHub Desktop.
Save seratch/2258356 to your computer and use it in GitHub Desktop.
Monty Hall problem
// http://en.wikipedia.org/wiki/Monty_Hall_problem
// http://d.hatena.ne.jp/hiratara/20120330/1333122309
import scala.util.Random._
case class Door(index: Int, isCar: Boolean)
def chooseDoor(doors: Seq[Door]): Door = doors(nextInt(doors.size))
object MontyHall {
val NUM_OF_DOORS = 3
def prepareDoors(): Seq[Door] = {
val doorToCar = nextInt(NUM_OF_DOORS)
(0 until NUM_OF_DOORS) map { x => Door(x, x == doorToCar) }
}
def choose(doors: Seq[Door], chosen: Door): Door = chooseDoor(doors) match {
case choice if choice != chosen && ! choice.isCar => choice
case _ => choose(doors, chosen)
}
}
case class Player(doors: Seq[Door]) {
lazy val firstChoice: Door = doors(nextInt(doors.size))
def choose(): Door = firstChoice
def reChoose(montyChoice: Door): Door = doors.find { door =>
door != firstChoice && door != montyChoice
}.get
}
def game(change: Boolean): Boolean = {
val doors: Seq[Door] = MontyHall.prepareDoors()
val player = new Player(doors)
val firstChoice = player.choose()
val montyChoice = MontyHall.choose(doors, firstChoice)
val finalChoice = if (change) player.reChoose(montyChoice) else firstChoice
finalChoice.isCar
}
def calculateWinRate(times: Int, change: Boolean): Double = {
val winCount = (1 to times) map { _ => game(change) } count (win => win)
winCount.toDouble / times.toDouble * 100
}
val times = 10000
println("first choice : %.2f %%".format(calculateWinRate(times, false)))
println("changed : %.2f %%".format(calculateWinRate(times, true)))
// vim: set ts=4 sw=4 et:
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment