Monty Hall probleem (drie-deuren quiz paradox)

Thursday 14 March 2013, 23:33:00 | diversen

Quiz met 3 deuren. Achter 1 deur zit de auto, achter 2 andere zit de mispoes. Je mag 1 deur kiezen van de Quizmaster. Deze opent vervolgens een andere deur, waar -altijd- een mispoes (geit) achter zit.

De quizmaster vraagt dan of je je deur keuze wilt wisselen of dat je bij je oorspronkelijke keuze blijft.

VRAAG: moet je wisselen of niet? (Heb je meer kans op de auto als je halverwege wisselt, of maakt het niet uit?)

Je zou zeggen dat het niks uitmaakt, maar dat is dus niet waar ^_^ Dit staat bekend als het 3-deuren probleem, ook wel het Willem-Ruis-probleem of het Monty-Hall-problem genoemd.

Empirisch bewijs volgt hieronder als Java programmaatje die duizenden quizzes simuleert en de winstresultaten daarna print. En daarmee aantoont dat het inderdaad een grotere kans op de auto oplevert als je wel van deur wisselt.

Ook de "green visitor" (alien) zit er in: die halverwege de quiz komt binnenvallen zonder dus weet te hebben van de eerste deurkeuze, en een willekeurige deur kiest van de overgebleven twee deuren.

import java.util.HashSet;
import java.util.Iterator;
import java.util.Random;

public class ThreeDoorsQuiz {

	public static void main(String[] args)
	{
		ThreeDoorsQuiz quiz = new ThreeDoorsQuiz();
		quiz.run();
	}
	
	public void run()
	{
		int aantal_simulaties = 100000;
		int aantal_autos_bij_niet_switchen = 0;
		int aantal_autos_bij_switchen = 0;
		int aantal_autos_alien = 0;

		char deuren[] = new char[3];
		Random rnd = new Random();
		
		for(int i=0; i<aantal_simulaties; ++i)
		{
			// bepaal achter welke deur de auto 'a' zit, andere 2 deuren zijn geiten 'g'
			deuren[0] = deuren[1] = deuren[2] = 'g';
			deuren[rnd.nextInt(3)] = 'a';
			
			// kandidaatkeuze
			int kandidaat = rnd.nextInt(3);
			
			// quizmaster kiest 1 van de 2 andere deuren, toont de geit
			int quizmaster;
			for(quizmaster=0; quizmaster<3; ++quizmaster)
			{
				if(quizmaster==kandidaat) continue;
				if(deuren[quizmaster]=='g') break;
			}
			
			// kandidaat die niet switched
			if(deuren[kandidaat]=='a') aantal_autos_bij_niet_switchen++;
			
			// kandidaat die wel switched naar de andere dichte deur
			HashSet<Integer> over = new HashSet<Integer>() {{
				add(0);
				add(1);
				add(2);
			}};
			over.remove(kandidaat);
			over.remove(quizmaster);
			kandidaat = over.iterator().next();
			if(deuren[kandidaat]=='a') aantal_autos_bij_switchen++;
			
			// green visitor kiest willekeurige deur van de overgebleven 2
			over = new HashSet<Integer>() {{
				add(0);
				add(1);
				add(2);
			}};
			over.remove(quizmaster);
			Iterator<Integer> iter = over.iterator();
			int visitor = iter.next();
			if(rnd.nextFloat()>0.5)
				visitor = iter.next();
			if(deuren[visitor]=='a') aantal_autos_alien++;
		}
		
		System.out.println("aantal quizzes: "+aantal_simulaties);
		System.out.println(String.format("gewonnen bij niet switchen: %d (%f %%)", 
				aantal_autos_bij_niet_switchen,
				(double)aantal_autos_bij_niet_switchen / aantal_simulaties * 100.0));
		System.out.println(String.format("gewonnen bij wel switchen:  %d (%f %%)",
				aantal_autos_bij_switchen,
				(double)aantal_autos_bij_switchen / aantal_simulaties * 100.0));
		System.out.println(String.format("gewonnen door de alien:     %d (%f %%)",
				aantal_autos_alien,
				(double)aantal_autos_alien / aantal_simulaties * 100.0));
	}
}

Runnen levert op:

aantal quizzes: 100000
gewonnen bij niet switchen: 33400 (33,400000 %)
gewonnen bij wel switchen:  66600 (66,600000 %)
gewonnen door de alien:     50054 (50,054000 %)

Q.E.D. 8-)

People have replied:

Irmen de Jong

2013-03-28 22:27:00

Zoals gewoonlijk is de Python implementatie een stuk leesbaarder

from __future__ import division
import random

deuren=['a','g','g']

aantal_autos_bij_niet_switchen = 0
aantal_autos_bij_switchen = 0
aantal_autos_alien = 0

aantal_simulaties = 100000

for i in range(aantal_simulaties):
    random.shuffle(deuren)
    kandidaat = random.randint(1,3)
    anderetwee = {1,2,3} - {kandidaat}
    quizmaster = anderetwee.pop()
    if deuren[quizmaster-1] == 'a':
        quizmaster = anderetwee.pop()
        assert deuren[quizmaster-1] =='g'

    if deuren[kandidaat-1] == 'a':
        aantal_autos_bij_niet_switchen += 1
    kandidaat = ({1,2,3} - {kandidaat, quizmaster}).pop()
    if deuren[kandidaat-1] == 'a':
        aantal_autos_bij_switchen += 1

    alien = random.choice(list({1,2,3} - {quizmaster}))
    if deuren[alien-1] == 'a':
        aantal_autos_alien += 1

print "aantal quizzes:", aantal_simulaties
print "niet switchen: {0} ({1} %)".format(
    aantal_autos_bij_niet_switchen, aantal_autos_bij_niet_switchen / aantal_simulaties * 100)
print " wel switchen: {0} ({1} %)".format(
    aantal_autos_bij_switchen, aantal_autos_bij_switchen / aantal_simulaties * 100)
print "green visitor: {0} ({1} %)".format(
    aantal_autos_alien, aantal_autos_alien / aantal_simulaties * 100)