Skip to content

Instantly share code, notes, and snippets.

@cedricbellet
Last active September 19, 2016 21:22
Show Gist options
  • Save cedricbellet/c07136ecdb3524ab802a679c916f5bb6 to your computer and use it in GitHub Desktop.
Save cedricbellet/c07136ecdb3524ab802a679c916f5bb6 to your computer and use it in GitHub Desktop.
Simulation of the Monty Hall Problem
// 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!!
*/
// 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