Rでモンティ・ホール問題

Rで モンティ・ホール問題 を試みます。

モンティ・ホール問題の説明

モンティ・ホール問題は、アメリカのゲームショー番組「Let’s Make a Deal」に由来する確率論の問題です。司会者の名前がモンティ・ホールだったことから、この名前がついています。

問題のシナリオは以下の通りです。

  1. 設定

    • あなたの前には3つの閉じたドアがあります。
    • 1つのドアの後ろには景品(車)があり、他の2つのドアの後ろにはハズレ(ヤギ)があります。
    • あなたはどのドアの後ろに何があるか知りません。
  2. 挑戦者の最初の選択

    • あなたは景品が入っていると思うドアを1つ選びます。
  3. 司会者の行動

    • 司会者は、どのドアに景品があるかを知っています。
    • 司会者は、あなたが選ばなかった残りの2つのドアのうち、必ずハズレ(ヤギ)が入っているドアを1つ開けて見せます。
  4. 最後の選択

    • ここで司会者はあなたに問いかけます。
    • 「最初に選んだドアのままにしますか? それとも、残っているもう一方のドアに変更しますか?」

【問題】

このとき、あなたはドアを変更するべきでしょうか? それとも変更しないべきでしょうか? どちらが景品を当てる確率が高いでしょうか?

【結論と解説】

直感的には「残ったドアは2つだから、どちらを選んでも確率は1/2(50%)だろう」と考えがちですが、これは間違いです。

正解は「ドアを変更した方が、当たる確率が2倍になる」です。

  • 変更しない場合:当たる確率は 1/3
  • 変更する場合:当たる確率は 2/3

なぜそうなるのかを説明します。

  • 最初に当たり(車)のドアを選ぶ確率1/3 です。
  • 最初にハズレ(ヤギ)のドアを選ぶ確率2/3 です。

この2つのシナリオを考えてみましょう。

  • シナリオ1:最初に当たりのドアを選んでいた場合(確率1/3)

    • この場合、司会者は残りの2つのハズレのドアのどちらかを開けます。
    • あなたが変更すると、必ずハズレになります。
    • あなたが変更しないと、当たります。
  • シナリオ2:最初にハズレのドアを選んでいた場合(確率2/3)

    • この場合、残りのドアは「当たり」と「ハズレ」が1つずつです。
    • 司会者はハズレのドアを開けなければならないので、必ずもう一方のハズレのドアを開けます。
    • その結果、残っている閉まったドアは必ず当たりのドアになります。
    • あなたが変更すると、必ず当たります。
    • あなたが変更しないと、ハズレになります。

まとめると、

  • 変更して勝つのは、最初にハズレを選んでいた場合です(確率2/3)。
  • 変更せずに勝つのは、最初に当たりを選んでいた場合です(確率1/3)。

したがって、ドアを変更する方が有利な戦略と言えます。


R言語によるシミュレーション

この直感に反する結果を確かめるために、R言語でシミュレーションを行ってみましょう。多数の試行を繰り返すことで、確率が理論値(1/3 と 2/3)に近づく様子を確認できます。

Rコード

set.seed(20250712)

options(scipen = 999)

# シミュレーションの試行回数を設定
n_simulations <- 100000

# 結果を記録するための変数を初期化
stay_wins <- 0 # ドアを変更せずに勝った回数
switch_wins <- 0 # ドアを変更して勝った回数

# シミュレーションのループ
for (i in 1:n_simulations) {
  # 1. ドアの設定
  doors <- 1:3

  # 2. 当たりのドアをランダムに決める
  car_door <- sample(doors, 1)

  # 3. 挑戦者の最初の選択をランダムに決める
  player_choice <- sample(doors, 1)

  # 4. 司会者が開けるドアを決める
  #    司会者は「挑戦者が選んでいない」かつ「当たりではない」ドアを開ける
  host_can_open <- setdiff(doors, c(player_choice, car_door))

  # 司会者が開けるドアを確定する
  if (length(host_can_open) == 1) {
    host_opens <- host_can_open
  } else {
    # 候補が複数ある場合は、その中からランダムに1つ選ぶ
    host_opens <- sample(host_can_open, 1)
  }

  # 5. 挑戦者が変更した場合に選ぶことになるドアを決める
  #    挑戦者の選択でもなく、司会者が開けたドアでもないドア
  switch_door <- setdiff(doors, c(player_choice, host_opens))

  # 6. 結果の判定
  #    a. 変更しなかった場合 (stay)
  if (player_choice == car_door) {
    stay_wins <- stay_wins + 1
  }

  #    b. 変更した場合 (switch)
  if (switch_door == car_door) {
    switch_wins <- switch_wins + 1
  }
}

# 7. 結果の表示
cat("シミュレーション試行回数:", n_simulations, "\n")
cat("-----------------------------------\n")

# 変更しなかった場合の勝率
stay_win_rate <- stay_wins / n_simulations
cat("ドアを変更しなかった場合の勝利数:", stay_wins, "\n")
cat("ドアを変更しなかった場合の勝率:", sprintf("%.4f", stay_win_rate), "(理論値: 1/3 ≈ 0.3333)\n\n")

# 変更した場合の勝率
switch_win_rate <- switch_wins / n_simulations
cat("ドアを変更した場合の勝利数:", switch_wins, "\n")
cat("ドアを変更した場合の勝率:", sprintf("%.4f", switch_win_rate), "(理論値: 2/3 ≈ 0.6667)\n")
シミュレーション試行回数: 100000 
-----------------------------------
ドアを変更しなかった場合の勝利数: 33181 
ドアを変更しなかった場合の勝率: 0.3318 (理論値: 1/3 ≈ 0.3333)

ドアを変更した場合の勝利数: 66819 
ドアを変更した場合の勝率: 0.6682 (理論値: 2/3 ≈ 0.6667)

結論

シミュレーション結果が示す通り、「ドアを変更しない」戦略の勝率は約33.2%(約1/3)に、「ドアを変更する」戦略の勝率は約66.8%(約2/3)に収束します。これにより、モンティ・ホール問題ではドアを変更する方が2倍有利であることが経験的に確認できました。

Rコードの解説

  1. n_simulations <- 100000:シミュレーションを100,000回繰り返す設定です。回数が多いほど、結果は理論値に近づきます。
  2. doors <- 1:3:3つのドアを 1, 2, 3 という数値のベクトルとして表現します。
  3. car_door <- sample(doors, 1):3つのドアからランダムに1つを「当たり」のドアとして選びます。
  4. player_choice <- sample(doors, 1):挑戦者がランダムに1つのドアを選びます。
  5. host_can_open <- setdiff(doors, c(player_choice, car_door)):司会者が開ける可能性のあるドアの候補を計算します。setdiff()関数は、第1引数の集合から第2引数の集合の要素を取り除いたものを返します。

    • 挑戦者が当たりを選んだ場合、host_can_openにはハズレのドアが2つ入ります。
    • 挑戦者がハズレを選んだ場合、host_can_openには残りのハズレのドアが1つだけ入ります。
  6. if (length(host_can_open) == 1) { ... } else { ... }:司会者が開けるドアを確定させます。

    • if (length(host_can_open) == 1): 候補が1つしかない場合(挑戦者が最初にハズレを選んだ場合)は、sample()を使わずにその値を直接 host_opens に代入します。
    • else: 候補が2つある場合(挑戦者が最初に当たりを選んだ場合)は、sample()を使ってその2つの候補からランダムに1つを選びます。
  7. switch_door <- setdiff(doors, c(player_choice, host_opens)):挑戦者が「変更する」場合に選ぶことになるドアを特定します。これは、全てのドアから「最初の選択」と「司会者が開けたドア」を除いた、残りの1つのドアです。
  8. if (player_choice == car_door):【変更しない】戦略の勝利条件です。挑戦者の最初の選択が当たりなら、勝利カウントを1増やします。
  9. if (switch_door == car_door):【変更する】戦略の勝利条件です。変更先のドアが当たりなら、勝利カウントを1増やします。
  10. cat(...):最後に、それぞれの戦略での総勝利数と勝率を計算して出力します。

以上です。