3囚人問題は有名だけど、こちらを見かけたのは恥ずかしながら初めて。
「プレイヤーの前に3つのドアがあって、1つのドアの後ろには景品の新車が、2つのドアの後ろにはヤギ(はずれを意味する)がいる。プレイヤーは新車のドアを当てると新車がもらえる。プレイヤーが1つのドアを選択した後、モンティが残りのドアの内ヤギがいるドアを開けてヤギを見せる。
ここでプレイヤーは最初に選んだドアを、残っている開けられていないドアに変更しても良いと言われる。プレイヤーはドアを変更すべきだろうか?」
答えは、変更した方が勝率が高くなる。ベイズの定理できちんと考えれば答えは出るのだけど、非常に嘘っぽく感じてしまうのがこの問題の特徴*1。嘘っぽいなら実際やらせて確かめてみればいい。
import scala.util.Random._ def didWinGame(isChange: Boolean): Boolean = { val doors: Array[Boolean] = Array(false, false, false) doors(nextInt(3)) = true val playerChoice = nextInt(3) def tryChoosing(): Int = { val choice = nextInt(3) if (choice != playerChoice && ! doors(choice)) choice else tryChoosing() } val montyChoice = tryChoosing() val finalAnswer = if (isChange) List(0, 1, 2).filter( (x: Int) => x != playerChoice && x != montyChoice )(0) else playerChoice return doors(finalAnswer) } def winningRate(doGame: () => Boolean) = { val total = 10000 val winCount = (1 to total).map(_ => doGame()).count((x: Boolean) => x) winCount.toDouble / total.toDouble * 100 } println("not change: %.2f %%".format(winningRate(() => didWinGame(false)))) println("change: %.2f %%".format(winningRate(() => didWinGame(true))))
実行するとほぼ理論値となる。
not change: 33.18 % change: 66.38 %
*1:この嘘っぽさは、引用した問題文だけだと前提条件が説明不足だってのもあるけど