Если вы смотрели фильм «21», то скорее всего вспомните, как профессор объясняет студентам классическую задачу с тремя дверями. За одной дверью — машина, а двумя другими — самокаты. Игрок выбирает дверь, но пока не открывает её. Затем ведущий открывает одну из оставшихся дверей, за которой точно находится самокат, и предлагает игроку поменять свой выбор.

Что же выбрать, чтобы открыть дверь с машиной - менять или нет?

Отрывок из фильма (задача с 1.11):

Интуиция нам подсказывает: вероятность, что за одной из оставшихся дверей будет машина — 1/2. Формально же оказывается, что:

  • если не менять дверь — шанс выиграть 1/3,

  • если менять — шанс выиграть 2/3.

Как так получилось и почему решение задачи кажется нелогичным? Разберем в статье:

  • где именно нас обманывает интуиция;

  • почему ведущий — главная "проблема" задачи;

  • смоделируем эксперимент кодом;

  • и посмотрим, как это выглядит в более привычных для мозга числах.

Где и почему ломается интуиция

Интуитивное 1/2 появляется из-за такой скрытой мысли:

Сейчас передо мной две двери. Я ничего о них не знаю. Значит, шансы равны.

Но это неправда, мы уже кое-что знаем. Во-первых, вы уже выбрали одну дверь. Во-вторых, ведущий открыл дверь не случайно - он знает где машина и специально выбирает дверь с самокатом. То есть изначальная ситуация «3 неизвестные двери» превратилась в более хитрую — «одна выбранная дверь + одна отфильтрованная ведущим».

Если мы выбрали Дверь №1, то шанс того, что машина будет за №2 ИЛИ №3 - 2/3. При этом после того, как ведущий откроет дверь с самокатом - вероятность 2/3 переходит на Дверь №2 (теперь мы воспринимаем две двери как одну). Поэтому нам стоит поменять дверь, ведь шансы выиграть там больше! Конечно, этот эффект более заметен при повторении игр множество раз.

Роль ведущего: почему без него парадокса нет

Попробуем убрать ведущего из задачи.

Вы выбираете Дверь №1 - там самокат.
Затем случайным образом выбирается одна из двух оставшихся дверей и открывается. Если там оказался самокат, вам снова предлагают поменять выбор. В этом варианте вероятности действительно будут по 1/2:

  • потому что открытая ведущим дверь могла оказаться машиной (игра просто закончится),

  • а если она не оказалась, то условная структура задачки другая.

Именно эти три условия делают ваши шансы при смене двери равными 2/3:

  1. ведущий знает, где машина,

  2. никогда не открывает дверь с машиной,

  3. обязан открыть дверь с самокатом.

То есть условная структура такова, что мы считаем вероятность не просто «после открытия самоката», а «после того, как ведущий открыл дверь, и мы знаем, что игра не закончилась». Среди только тех партий, где игра дошла до момента "вам предложили сменить дверь", ваш первоначальный выбор оказывается удачным в половине случаев, а не в трети, как в классическом Монти Холле.

Поэтому если ведущий случаен — парадокс просто исчезает.

Смоделируем это на Python

Смоделируем классического Монти Холла в коде.

import random

def play_once(switch: bool) -> bool:
    """
    Играем одну партию в Монти Холла.
    param switch: если True — игрок всегда меняет дверь,
                  если False — всегда остается при своем выборе.
    return: True, если игрок выиграл машину.
    """
    doors = [0, 0, 0]  # 0 — самокат, 1 — машина
    prize_door = random.randrange(3)
    doors[prize_door] = 1

    # Игрок делает первый выбор
    first_choice = random.randrange(3)

    # Ведущий открывает одну из дверей (с самокатом), отличную от выбора игрока
    candidate_doors = [
        i for i in range(3)
        if i != first_choice and doors[i] == 0
    ]
    opened_by_host = random.choice(candidate_doors)

    if switch:
        # Игрок переходит на единственную оставшуюся закрытую дверь
        final_choice = [i for i in range(3)
                        if i not in (first_choice, opened_by_host)][0]
    else:
        # Игрок оставляет свой исходный выбор
        final_choice = first_choice

    return doors[final_choice] == 1


def simulate(trials: int = 100_000) -> None:
    print(f"Кол-во игр: {trials}\n")
    for switch in (False, True):
        wins = sum(play_once(switch) for _ in range(trials))
        p = wins / trials
        strategy = "не поменял дверь" if not switch else "поменял дверь"
        print(
            f"Стратегия: {strategy:15} -> "
            f"выигрышей: {wins:6} "
            f"({p:.3f}, то есть ~{p*100:.1f}%)"
        )


if __name__ == "__main__":
    simulate()
Кол-во игр: 100000

Стратегия: не поменял дверь -> выигрышей:  33309 (0.333, то есть ~33.3%)
Стратегия: поменял дверь   -> выигрышей:  66798 (0.668, то есть ~66.8%)

Что и подтверждает наши вычисленные вероятности) Видно, что стратегия "менять дверь" имеет примерно в два раза больше выигрышей.

Теперь смоделируем ситуацию со случайным ведущим!

import random

def simulate_random_host(trials: int = 100_000) -> None:
    """
    Вариант: ведущий не знает, где машина.
    Он случайно открывает одну из двух оставшихся дверей.
    Если там машина — игра сразу заканчивается.
    Если там самокат — он предлагает поменять дверь.
    """
    reached = 0        # игр, где дошли до "предложили сменить"
    ended_early = 0    # игр, где ведущий случайно открыл машину

    stay_wins = 0      # выигрыши, если НЕ менять дверь (среди достигших предложения)
    switch_wins = 0    # выигрыши, если МЕНЯТЬ дверь (среди достигших предложения)

    for _ in range(trials):
        doors = [0, 0, 0]
        prize_door = random.randrange(3)
        doors[prize_door] = 1

        first_choice = random.randrange(3)

        # Рандомный ведущий выбирает одну из двух оставшихся дверей
        candidate_doors = [i for i in range(3) if i != first_choice]
        opened_by_host = random.choice(candidate_doors)

        # Если он открыл машину -  игра закончилась, до предложения не дошли
        if doors[opened_by_host] == 1:
            ended_early += 1
            continue

        # Иначе он открыл козу и предлагает сменить дверь
        reached += 1

        stay_choice = first_choice
        switch_choice = [i for i in range(3)
                         if i not in (first_choice, opened_by_host)][0]

        if doors[stay_choice] == 1:
            stay_wins += 1
        if doors[switch_choice] == 1:
            switch_wins += 1

    print(f"Кол-во игр: {trials}")
    print(f"Игры дошли до предложения сменить дверь: {reached} (~{reached / trials:.3f})")
    print(f"Игра закончилась сразу (открыли машину): {ended_early} (~{ended_early / trials:.3f})")

    if reached > 0:
        print("Среди игр, где ведущий открыт самокат и предложил сменить дверь:")
        print(f" - если не менять дверь  -> выигрыш ≈ {stay_wins / reached:.3f}")
        print(f" - если менять дверь     -> выигрыш ≈ {switch_wins / reached:.3f}")
        

if __name__ == "__main__":
    simulate_random_host()

Результат:

Кол-во игр: 100000
Игры дошли до предложения сменить дверь: 66579 (~0.666)
Игра закончилась сразу (открыли машину): 33421 (~0.334)
Среди игр, где ведущий открыт самокат и предложил сменить дверь:
 - если не менять дверь  -> выигрыш ≈ 0.498
 - если менять дверь     -> выигрыш ≈ 0.502

А тут уже шансы выиграть примерно равны - 50/50. Но не забываем, что были игры, где игра закончилась сразу)

А если дверей много?

Три двери — скучно. Давайте возьмем, скажем, 100 дверей:

  1. Вы выбираете одну дверь из 100. Шанс попасть в машину = 1/100.

  2. Ведущий знает, где машина, и открывает 98 дверей с самокатами, оставляя закрытыми вашу дверь и еще одну, где возможно машина (а возможно — самокат).

  3. Если вы останетесь при своем выборе, то шанс все тот же — 1/100. Если вы перейдете на другую закрытую дверь, ваш шанс — 99/100.

Почему? Потому что вероятность, что вы промахнулись в первый раз — 99/100.Но ведущий, зная расположение машины, аккуратно «вычищает» все промахи, оставляя их в одном варианте.

Здесь уже интуиция работает хорошо - не стоит держаться за один шанс из 100 (ваш первый случайный выбор).

Итоги

  • В классическом парадоксе Монти Холла стратегия «сменить дверь» даёт шанс выиграть 2/3, а «оставаться при своём» — лишь 1/3. Поэтому дверь нужно менять!

  • Парадокс возникает из-за ведущего — он ведёт себя не случайно и использует знание о расположении приза.

  • В задаче мы попадаем в ловушку условной вероятности, которую замечаем не сразу. Нас интересует не просто шанс «где машина», а шанс «где машина при условии, что ведущий открыл именно эту дверь с самокатом и действовал по заданным правилам».

Парадокс Монти Холла — хорошее напоминание, что в реальных задачах важно учитывать не только факт события, но и механизм, который к нему привёл. А это уже прямая зона ответственности условных вероятностей и байесовского мышления.