Skip to content

Instantly share code, notes, and snippets.

@mr-parus
Last active January 10, 2020 21:37
Show Gist options
  • Save mr-parus/55ef43e1e73336b2f0ffa59352ad509f to your computer and use it in GitHub Desktop.
Save mr-parus/55ef43e1e73336b2f0ffa59352ad509f to your computer and use it in GitHub Desktop.
[JS] Monty Hall Problem simulation
One time case simulation:
Initial doors:
1)πŸšͺ
2)πŸšͺ🎁
3)πŸšͺ
--------------------------------------------------
Choosing one door:
Chosen door #3
1)πŸšͺ
2)πŸšͺ🎁
->3)πŸšͺ
--------------------------------------------------
Open one door:
1)
2)πŸšͺ🎁
->3)πŸšͺ
--------------------------------------------------
Open chosen door:
1)
2)πŸšͺ🎁
->3)
--------------------------------------------------
Loser!
N times simulation:
From 10000 experiments:
Without changing door: 32.9 %
With changing door: 67.10000000000001 %
// In the problem, you are on a game show, being asked to choose between three doors.
// Behind each door, there is either a car or a goat. You choose a door.
// The host, Monty Hall, picks one of the other doors, which he knows has a goat behind it,
// and opens it, showing you the goat. (You know, by the rules of the game, that Monty will always reveal a goat.)
// Monty then asks whether you would like to switch your choice of door to the other remaining door.
// Assuming you prefer having a car more than having a goat, do you choose to switch or not to switch?
// https://en.wikipedia.org/wiki/Monty_Hall_problem
// util logic
const getArray = (n) => Array.from({length: n});
const filterNull = (e) => e !== null;
const getRandomFromN = (n) => Math.floor(Math.random() * n);
const getRandomElement = (a) => a[getRandomFromN(a.length)];
// logging logic
let l = console.log;
const displayDivider = () => l('-'.repeat(50));
const displayDoors = (doors) => l(doors.map(({content, opened, chosen}, i) =>
`${chosen ? "->" : " "}${i + 1})${opened ? "" : "πŸšͺ"}${content}`).join("\n"));
// door logic
const PRIZE_VAL = "🎁";
const createDoor = ({opened = false, content = "", chosen = false} = {}) => ({opened, content, chosen});
const openDoorById = (doors, i) => doors.map((e, index) => index === i ? {...e, opened: true} : e);
const openChosenDoor = (doors) => doors.map((e) => e.chosen? {...e, opened: true} : e);
const choseDoorById = (doors, i) => doors.map((e, index) => index === i ? {...e, chosen: true} : {...e, chosen: false});
const setDoorContentById = (doors, i, val) => doors.map((e, index) => index === i ? {...e, content: val} : e);
const getInitialDoors = (n) => {
const doors = getArray(n).map(createDoor.bind(null, undefined));
return setDoorContentById(doors, getRandomFromN(n), PRIZE_VAL);
};
const chooseOneDoor = (doors) => {
const notOpenedAndNotChosenBeforeDoorsIndexes = doors.map(({opened, chosen}, i) => !chosen && !opened ? i : null).filter(filterNull);
const chosenIndex = getRandomElement(notOpenedAndNotChosenBeforeDoorsIndexes);
l(`Chosen door #${chosenIndex + 1}`);
return choseDoorById(doors, chosenIndex);
};
const openOneDoor = (doors) => {
const notOpenedAndNotTargetIndexes = doors.map(({opened, content, chosen}, i) => !chosen && !opened && content !== PRIZE_VAL ? i : null).filter(filterNull);
const openIndex = getRandomElement(notOpenedAndNotTargetIndexes);
return openDoorById(doors, openIndex);
};
const isTargetDoorChosen = (doors) => {
const result = doors.reduce((acc, {content, chosen}) => { return content === PRIZE_VAL && chosen?true: acc }, false);
l(result ? "Winner!" : "Loser!");
return result;
};
const experiment = (change = false) => {
l(`Initial doors:`);
let doors = getInitialDoors(3);
displayDoors(doors);
displayDivider();
l(`Choosing one door:`);
doors = chooseOneDoor(doors, []);
displayDoors(doors);
displayDivider();
l(`Open one door:`);
doors = openOneDoor(doors);
displayDoors(doors);
displayDivider();
if (change) {
l(`Choosing another door:`);
doors = chooseOneDoor(doors);
displayDoors(doors);
displayDivider();
}
l(`Open chosen door:`);
doors = openChosenDoor(doors);
displayDoors(doors);
displayDivider();
return +isTargetDoorChosen(doors);
};
const calculate = (n) => {
l = () => {};
let resultsWithChangingDoor = 0;
let resultsWithoutChangingDoor = 0;
for (let i = 0; i < n; i++) {
const resultWithChangingDoor = experiment(true);
if (resultWithChangingDoor) {
resultsWithChangingDoor +=1;
} else {
resultsWithoutChangingDoor +=1;
}
}
console.log(`
From ${n} experiments:
Without changing door: ${resultsWithoutChangingDoor / n * 100} %
With changing door: ${resultsWithChangingDoor / n * 100} %`);
};
// N times
calculate(10000);
// 1 time
experiment()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment