モンティ・ホール問題をCoffeeScriptで検証


モンティ・ホール問題とは

アメリカのTV番組で行われたあるゲームについての論争のこと。

  1. 司会者側がドアを三枚用意し、その内ふたつにはヤギを、残りの一枚には新車を隠す。
  2. 回答者はドアを一枚選ぶ。
  3. 司会者は回答者の選んでいないドアから一枚を開けて、ヤギを見せる。
  4. 司会者は回答者にドアを選び直したいか質問する。
  5. この時、回答者はドアを選び直した方が確率的には新車を得やすくなる(その差は2倍)。

確率が直感に反するため、議論になったそうです。
モンティ・ホール問題 - Wikipedia

検証

CoffeeScript
class MontyHall

  setDoor = (int)->
    arr = []
    while int
      arr.push('empty')
      int--
    return arr

  putCar = (doors)->
    int = parseInt(Math.random() * doors.length)
    arr = []
    for door, index in doors
      if index is int then arr.push('car') else arr.push('goat')
    return arr

  openDoor = (doors, firstChoice)->
    opened = false
    arr = []
    for door, index in doors
      if door is 'car' or index is firstChoice
        arr.push(door)
      else if !opened
        arr.push('opened')
        opened = true
      else
        arr.push('goat')
    return arr

  changeMind = (doors, firstChoice)->
    int = 0
    for door, index in doors
      unless index is firstChoice or door is 'opened'
        int = index
        break
    return int

  constructor: (@obj)->

  log: ()->
    conf =
      doors: if @obj and @obj.doors and typeof @obj.doors is 'number' then parseInt(@obj.doors) else 3
      tests: if @obj and @obj.tests and typeof @obj.tests is 'number' then parseInt(@obj.tests) else 2000
    tests = TESTS = conf.tests
    doors = setDoor(conf.doors)
    firstChoiceIsCorrect = secondChoiceIsCorrect = 0
    while tests
      doors = putCar(doors)
      firstChoice = parseInt(Math.random() * doors.length)
      doors = openDoor(doors, firstChoice)
      if doors[firstChoice] is 'car' then firstChoiceIsCorrect++
      secondChoice = changeMind(doors, firstChoice)
      if doors[secondChoice] is 'car' then secondChoiceIsCorrect++
      tests--
    console.log('firstChoiceIsCorrect', parseInt(firstChoiceIsCorrect / TESTS * 1000) / 10 + '%')
    console.log('secondChoiceIsCorrect', parseInt(secondChoiceIsCorrect / TESTS * 1000) / 10 + '%')
    return

new MontyHall
  doors: 3
  tests: 2000
.log()

結果

ドア3枚で、2000回のテスト結果です。

firstChoiceIsCorrect – "33.2%"
secondChoiceIsCorrect – "66.7%"

確率が2倍になりました。
ちなみに「ドアを4つに増やして、ヒントをひとつ与える」場合でも同様に、確率が2倍になります。

解説

3つドアがある場合、新車を当てる確率は1/3。ハズす確率は2/3。
ドアを選び直すことによって損をするのは、1/3の確率。
ドアを選び直すことによって得をするのは、その逆なので2/3の確率。
ということで、66%ほどの割合で新車をゲット。元の確率の2倍になります。