スキップしてメイン コンテンツに移動

当然に思えるものほど二重に確認しよう

ノーベル経済学賞受賞者のフィッシャー・ブラック氏が出した問題です。

ひとりの出場者が3つの扉に向かっている。出場者はひとつの扉の後ろにとても好ましい賞品-たとえばすてきな車-が隠されているのを知っている。他のふたつの扉の後ろにはいくらかやっかいな好ましからざるもの-たとえば山羊-が隠されている。出場者はひとつの扉を選び、そこに隠されている商品を受け取る。
ところが娯楽番組の司会者-モンティ・ホール-は出場者をしつこく悩ませ・たぶらかし・勧誘して、心を変えさせようとし、どれがすてきな扉であるか出場者が困惑するようにしむける。
出場者が扉の中からひとつを選ぶと、モンティ・ホールは「OK、キャロル、x番の扉を開けてください」と言い、アシスタントが開けるとそこには山羊がいる。司会者は何番の賞品が高価なものであるかを知っており、開ける順番を心得ている。
ここでモンティ・ホールは「選択を変えますか?」と出場者に尋ねる。
このときそのままで良いのか、乗り換えた方が有利なのか?

予想してみてください。

私は、乗り換えようが乗り換えないでおこうが、同じ確率なんじゃないかなと思いました。
でも、ここでは選択を変更したほうが有利なんだそうです。
当然に思えるものほど二重に確認しなくてはいけないという教訓らしいのですけど、私じゃ2回確認したところで正しい選択は出来なさそうです。

プログラムを作って検証してみることにしました。

class MontyHall

  def initialize
    @door = ['goat', 'goat', 'goat']
    @door[rand(3)] = 'car'
  end

  def  show
    @door.each_index do |i|
      p 'door' + i.to_s + ': ' + @door[i]
    end
  end

  def select(answer)
    @SelectDoor = answer
    p 'You selected the door' + @SelectDoor.to_s
    if rand(2) == 0
      0.step(@door.length, 1) do |i|
        if i != answer && @door[i] == 'goat'
          @OpenDoor = i
        end
      end
    else
      @door.length.step(0, -1) do |i|
        if i != answer && @door[i] == 'goat'
          @OpenDoor = i
        end
      end
    end
    p 'A goat is in the door' + @OpenDoor.to_s
  end

  def switch(answer)
    if answer == false
      p "You didn't switch your selection"
      self.show
      if @door[@SelectDoor] == 'car'
          p 'You get a car.'
          return true
      else
          p 'You get a goat.'
          return false
      end
    else
      p 'You switched your selection'
      self.show
      if @door[@SelectDoor] == 'goat' && @door[@OpenDoor] == 'goat'
          p 'You get a car.'
          return true
      else
        p 'You get a goat.'
        return false
      end
    end
  end
end

wina = 0
100.times do
  game = MontyHall.new
  game.select(rand(2))
  if game.switch(false) == true
    wina = wina + 1
  end
end

winb = 0
100.times do
  game = MontyHall.new
  game.select(rand(2))
  if game.switch(true) == true
    winb = winb + 1
  end
end

p "If you don't switch, you will win " + wina.to_s + "%."
p "If you switch, you will win " + winb.to_s + "%."

プログラムを書いてみると、実行するまでもなく、変更したほうが有利なんだなと言うことは理解できました。
リファクタリングの余地がたくさんありますが、これをきれいにしてしまうといかにも選択を変更したとき確率2/3を出そうとしているように見えてしまう見えてしまうので冗長なままにしてみました。

ニューヨークタイムズ紙にこの記事が載ったときは、1000通近くの批判的な手紙が来たそうです。

 編集者殿
「外れの山羊か、当たりの自動車か」という記事が出ていましたが、自動車よりも山羊のほうがいいという観点からの観察に欠けていたと思います。駐車するときに困惑しますが、山羊はすばらしい動物です。
        ローレ・セガール
        ニューヨーク、1991年7月22日
  -ジャック・D・シュワッガー、清水昭男訳「新マーケットの魔術師」より-

コメント