Last active
September 19, 2016 21:22
-
-
Save cedricbellet/c07136ecdb3524ab802a679c916f5bb6 to your computer and use it in GitHub Desktop.
Simulation of the Monty Hall Problem
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// node main.js | |
// This script simulates the Monty Hall problem, in which a player is offered | |
// to choose between 3 doors, only one of which hides a prize. After a first pick, | |
// the game master opens one of the no-prize doors which was not picked by the player. | |
// The player is then given a chance to amend their choice and pick the other | |
// remaining door. This simulation shows that a player sticking to their | |
// initial choice only have a 33% probability of finding the prize, deciding at | |
// random increases the probability to 50%, while systematically switching maxes out | |
// the probability at 67%. | |
'use strict'; | |
var debug = false; | |
function simulate(nSim, strategy) { | |
let rightGuesses = 0; | |
// repeat: | |
for (let i = 0; i < nSim; i++) { | |
// three doors, place the prize behind one of them | |
let prizeDoor = Math.floor(Math.random() * 3); | |
// pick a door | |
let choice = Math.floor(Math.random() * 3); | |
// open a door with no prize | |
let noPrizeDoors = [0, 1, 2].filter((val) => val != choice && val != prizeDoor); | |
let aNoPrizeDoor = noPrizeDoors[Math.floor(Math.random() * noPrizeDoors.length)]; | |
let alternateChoices = [0, 1, 2].filter((val) => val != choice && val != aNoPrizeDoor); | |
let alternateChoice = alternateChoices[Math.floor(Math.random() * alternateChoices.length)]; | |
let finalChoice; | |
// change the choice? | |
switch (strategy) { | |
case 'switch': | |
finalChoice = alternateChoice; | |
break; | |
case 'random': | |
Math.random() > 0.5 ? finalChoice = alternateChoice : finalChoice = choice; | |
break; | |
default: | |
finalChoice = choice; | |
} | |
// spit out a report | |
if (debug) console.log(`c: ${choice} a: ${alternateChoice} f: ${finalChoice} t: ${prizeDoor}`); | |
// note the result | |
if (finalChoice == prizeDoor) rightGuesses += 1; | |
} | |
console.log(rightGuesses / nSim); | |
} | |
simulate(10000); // if the player does not change their mind, p of winning is 0.33 | |
simulate(10000, 'random'); // if they choose at random when given the option, p = 0.5 | |
simulate(10000, 'switch'); // if they systematically select the other door, p = 0.67 | |
/* | |
The Switch Strategy | |
0 0 1 | |
If the player picks a 0 (2 out of 3 chances), the game master is forced to remove the other 0. | |
Hence by switching the player is guaranteed to win. If the player picks a 1 (1 chance out of 3), | |
they are on the other hand guaranteed to lose if they switch. On average the player's chances | |
with this strategy are therefore of 2/3, that is, 67%. | |
WHAT IF | |
If the player *knows* that the rule is enforced, then they should pursue the switch strategy | |
to secure the 67% win rate. What if however, an opened door reveals a 0, but there is no way | |
to know if this is chance or enforcement of the rule? | |
--> The player should switch anyway. | |
- If the rule is enforced, then the player has a 67% of winning when switching. | |
- If it is not (like in certain games where the game master can indeed show a prize | |
container), then the probability of winning is 50%, but switching does not alter this probability. | |
So by switching, the player covers some of the 'risk' that the rule might be enforced, improving | |
their probability of winning to somewhere between 0.5 <= p < 0.67, without having to know whether | |
the rule is actually enforced. ALWAYS SWITCH!! | |
*/ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// node alternate.js | |
// In this alternate scenario, the game master removes an arbitrary door. | |
// All probabilities fall down to 33%, because the game master enforces no rule; | |
// adding no information in the process of removing a door. | |
'use strict'; | |
var debug = false; | |
function simulate(nSim, strategy) { | |
let rightGuesses = 0; | |
// repeat: | |
for (let i = 0; i < nSim; i++) { | |
// three doors, place the prize behind one of them | |
let prizeDoor = Math.floor(Math.random() * 3); | |
// pick a door | |
let choice = Math.floor(Math.random() * 3); | |
// open a door with no prize | |
let otherDoors = [0, 1, 2].filter((val) => val != choice); | |
let alternateChoice = otherDoors[Math.floor(Math.random() * otherDoors.length)]; | |
let finalChoice; | |
// change the choice? | |
switch (strategy) { | |
case 'change': | |
finalChoice = alternateChoice; | |
break; | |
case 'random': | |
Math.random() > 0.5 ? finalChoice = alternateChoice : finalChoice = choice; | |
break; | |
default: | |
finalChoice = choice; | |
} | |
// spit out a report | |
if (debug) console.log(`c: ${choice} a: ${alternateChoice} f: ${finalChoice} t: ${prizeDoor}`); | |
// note the result | |
if (finalChoice == prizeDoor) rightGuesses += 1; | |
} | |
console.log(rightGuesses / nSim); | |
} | |
simulate(10000); // regardless of the strategy, the win rate is now 33% | |
simulate(10000, 'random'); | |
simulate(10000, 'change'); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment