Paradoks teleturnieju


Załóżmy, że bierzesz udział w teleturnieju i masz do wyboru trzy bramki: Za jedną znajduje się samochód; za pozostałymi kozy. Wybierasz bramkę, powiedzmy nr 1, a prowadzący, który wie, co jest za bramkami, otwiera inną bramkę, powiedzmy nr 3, za którą jest koza. Następnie mówi do Ciebie: „Czy chcesz wybrać bramkę nr 2?”

W tym momencie 2 bramki są zamknięte i wiesz, że za jedną z nich jest samochód, więc masz 50% szans na wygraną, niezależnie od tego, czy pozostaniesz przy swoim wyborze, czy go zmienisz, prawda?



Otóż nie! Dokonując wstępnego wyboru, miałeś tylko 1/3 szans na trafienie. Jeśli zmienisz teraz wybór, prawdopodobieństwo wygranej wzrośnie. Nie wierzysz mi? Nie dziwię się, to bardzo sprzeczne z intuicją. Ale zagraj w poniższą grę, aby sprawdzić to samodzielnie.



Wybierz losową bramkę, a następnie gospodarz odsłoni inną bramkę z kozą. Kliknij „zachowaj zieloną bramkę”. Prawdopodobnie (z prawdopodobieństwem 2/3) przegrasz. Powtórz to kilka razy. Lub pozwól komputerowi grać za Ciebie, używając przycisku „Automatycznie uruchom 100 gier typu „zachowaj””. Procent wygranych w grach typu „zachowaj” będzie uparcie wracał do 33%.



Teraz spróbuj uruchomić kilkaset gier typu „zmień” i zobacz, jak prawdopodobieństwo wzrasta do około 67%.

Nie ma tu żadnej sztuczki - to czysta matematyka. Pełny kod znajduje się poniżej. Ponadto wszystko jest logowane w konsoli. Baw się dobrze!


<html>
<meta http-equiv="Content-Typecontent="text/htmlcharset=utf-8"/>
<style>
button {
    font-size: 80px;
     width33.33%;
}
 
div {
    white-spacepre;
    border-stylesolid;
        line-height2;
        font-size: 20px;
}
</style>
<body>
<script>
const buttons = [];
const doors = [];
const massGameCount = 100// liczba gier uruchamianych po kliknięciu przycisków „automatycznych”
let winningDoor// numer bramka z nagrodą (samochód)
let doorSelected// numer bramki wybranej przez gracza
let doorRevealed// numer bramki odsłoniętej przez prowadzącego
let mode// wybór użytkownika: zachowaj lub zmień
// tylko dla celów statystycznych: liczba rozegranych gier i odpowiednie wygrane:
let keepGames = 0;
let changeGames = 0;
let keepWins = 0;
let changeWins = 0;
 
function initGame() {
    textBar.textContent = "Wybierz bramkę";
    keepButton.hidden = true// ukryj wszystkie przyciski
    changeButton.hidden = true;
    massKeepButton.hidden = true;
    massChangeButton.hidden = true;
    mode = "keep"; // tryb gry "zachowaj" vs "zmień"
 
    for (let i = 0i < 3i++) { // wyświetl 3 zamknięte bramki, szare i aktywne:
        buttons[i].innerHTML = "🚪";
        buttons[i].style.background = 'grey';
        buttons[i].disabled = false;
        doors[i] = "goat";
        // początkowo wszystkie bramki mają kozę
    }
    winningDoor = Math.floor(Math.random() * 3); // zastąp kozę za losową bramką nagrodą - samochodem
    console.log('Bramka z nagrodą: ' + winningDoor);
}
 
function doorClick(index) {
    // gracz wybiera pierwszą bramkę
    console.log('Wybrana bramka: ' + index);
    doorSelected = index;
    buttons[index].style.background = 'green';
    textBar.textContent = "Wybrałeś zieloną bramkę.\nProwadzący odsłonił inną bramkę z kozą.\nCzy chciałbyś zmienić swój wybór (na szarą bramkęczy zachować pierwotny wybór?";
    keepButton.hidden = false;
    changeButton.hidden = false;
    // prowadzący losowo odsłania jedna bramka z kozą:
    doorRevealed = "none";    // początkowo żadne bramki nie są odsłonięte
    let direction = -1;    // początkowo załóż kierunek wyszukiwania od prawej do lewej
    let currentDoor = 2;    // zacznij od bramki z prawej
    if (Math.random() < 0.5) { // 50% prawdopodobieństwa zmiany kierunku
        direction = 1// odwróć kierunek
        currentDoor = 0// przełącz na bramkę z lewej
    }
 
    for (let i = 0i < 3i++) {        // sprawdź każdą bramkę
        buttons[i].disabled = true;
        // jeśli to nie jest bramka wygrywająca, nie wybrane przez użytkownika i żadne bramki nie zostały jeszcze odsłonięte:
        if (currentDoor !== winningDoor && currentDoor !== doorSelected && doorRevealed == "none") {
            buttons[currentDoor].innerHTML = "🐐";  // odsłoń bramkę
            doorRevealed = currentDoor;
            console.log("Odsłonięta bramka: " + doorRevealed);
        }
        currentDoor = currentDoor + direction;
        // kontynuuj wyszukiwanie w tym samym kierunku
    }
}
 
function listenerForI(i) {
    // dodaj nasłuchiwacz kliknięć do każdego przycisku
    buttons[i].addEventListener('mousedown', function() {
        doorClick(i);
    }, false);
}
 
function runMassGames(massMode) {
    // automatycznie uruchom wiele gier
    for (let i = 0i < massGameCounti++) {
        initGame();
        doorClick(Math.floor(Math.random() * 3));
        // wybierz losową bramkę dla gracza
        if (massMode == "change") {
            // gra typu "zmień"
            changeButton.click();
        } else {
            keepButton.click();
            // gra typu "zachowaj"
        }
    }
}
 
for (let i = 0i < 3i++) {
    // utwórz przyciski do wyświetlania bramek
    buttons[i] = document.createElement('button');
    document.body.appendChild(buttons[i]);
    listenerForI(i);
}
 
const textBar = document.createElement('div');
// do wyświetlania wiadomości dla gracza
document.body.appendChild(textBar);
 
const keepButton = document.createElement('div');
// div używany jako przycisk do wyboru trybu gry "zachowaj"
keepButton.textContent = 'Kliknij tutajaby zachować zieloną bramkę';
document.body.appendChild(keepButton);
 
const changeButton = document.createElement('div');
// div używany jako przycisk do wyboru trybu gry "zmień"
changeButton.textContent = 'Kliknij tutajaby zmienić na szarą bramkę';
document.body.appendChild(changeButton);
 
const massChangeButton = document.createElement('div');
massChangeButton.textContent = 'Kliknij tutajaby automatycznie uruchomić 100 gier typu "Zmień"';
document.body.appendChild(massChangeButton);
 
const massKeepButton = document.createElement('div');
massKeepButton.textContent = 'Kliknij tutajaby automatycznie uruchomić 100 gier typu "Zachowaj"';
document.body.appendChild(massKeepButton);
 
// zdefiniuj zachowanie każdego przycisku/diva:
textBar.onclick = initGame;
 
massChangeButton.onclick = function() {
    runMassGames("change");
}
;
 
massKeepButton.onclick = function() {
    runMassGames("keep");
}
;
 
keepButton.onclick = function() {
    // gracz wybiera grę typu "zachowaj"
    keepButton.hidden = true;
    changeButton.hidden = true;
    for (let i = 0i < 3i++) {
        if (i == winningDoor) {
            buttons[i].innerHTML = '🚗';
        } else {
            buttons[i].innerHTML = "🐐";
        }
    }
    if (mode == "change") {
        // zaktualizuj statystyki
        changeGames++;
    } else {
        keepGames++;
    }
    if (doorSelected == winningDoor) {
        textBar.textContent = "Wygrałeś!\nKliknij tutajaby zrestartować.";
        console.log("Wygrana");
        if (mode == "change") {
            changeWins++;
        } else {
            keepWins++;
        }
    } else {
        textBar.textContent = "Przegrałeś!\nKliknij tutajaby zrestartować.";
        console.log("Przegrana");
    }
    let stats = "\n\nGryw których zachowałeś początkową bramkę: " + keepGames;
    stats = stats + "\nWygrane w grach 'zachowaj': " + keepWins;
    if (keepGames) {
        stats = stats + "\nProcent wygranych w grach 'zachowaj': " + Math.floor(keepWins / keepGames * 100);
    }
    stats = stats + "\nGryw których zmieniłeś bramkę na inną: " + changeGames;
    stats = stats + "\nWygrane w grach 'zmień': " + changeWins;
    if (changeGames) {
        stats = stats + "\nProcent wygranych w grach 'zmień': " + Math.floor(changeWins / changeGames * 100);
    }
    textBar.textContent = textBar.textContent + stats;
    console.log('----------------------');
    massKeepButton.hidden = false;
    massChangeButton.hidden = false;
}
;
 
changeButton.onclick = function() { // gracz wybiera grę typu "zmień":
    mode = "change";
    buttons[doorSelected].style.background = 'gray';
    let newReveal;
    for (let i = 0i < 3i++) {
        if (i !== doorSelected && i !== doorRevealed) {  // zmień wybraną bramkę na te nieodsłonięte
            newReveal = i;
            console.log("Zmiana na bramkę " + newReveal);
        }
    }
    doorSelected = newReveal;
    buttons[doorSelected].style.background = 'green';
    keepButton.onclick();  // kontynuuj tak, jakby to była gra typu "zachowaj"
}
;
 
initGame(); // zainicjuj pierwszą grę
 
</script>
</body>
</html>
Cały kod jest udostępniony na licencji MIT

Więcej samouczków JS

Gra "Wieża" - 84 linie JavaScript

Fraktale - 25 linii

Sinus scroll - 30 linii

Gra "Angry Chickens"

Animowane krzywe kwadratowe - 40 linii

Animowane konstelacje cząsteczek - 42 linie

Eksperyment z enginem fizyki