Unveiling the Monty Hall Problem: A JavaScript Simulation

Vardan Hakobyan - Sep 21 - - Dev Community

Have you ever pondered the Monty Hall problem? This classic probability puzzle has baffled both mathematicians and casual thinkers for years. Today, we’re going to demystify this counterintuitive puzzle using the power of JavaScript.

The Monty Hall Problem: A Quick Recap

Imagine this scenario:

  1. You’re on a game show facing three closed doors.
  2. Behind one door lies a shiny new car; behind the other two, just goats.
  3. You pick a door (let’s call it Door A), hoping for the car.
  4. The host, Monty Hall, who knows what’s behind each door, opens another door revealing a goat.
  5. Now, Monty offers you a choice: stick with Door A or switch to the remaining unopened door.

Here’s the million-dollar question: Should you switch doors or stay put? Does it even matter?

Surprisingly, the odds aren’t 50–50. If you switch, you’ll win the car 2/3 of the time! Sounds counterintuitive, right? Let’s prove it with code.

Setting Up Our JavaScript Simulator

First, let’s create a simple Node.js app. If you’re familiar with the process, feel free to skip this section.

Otherwise, follow these steps:

  1. Open your terminal and navigate to your desired project folder.
  2. Run these commands:
mkdir monty-hall-problem
cd monty-hall-problem
Enter fullscreen mode Exit fullscreen mode

Now, create an entry file, where we will write the actual code:

touch index.js
Enter fullscreen mode Exit fullscreen mode

That’s it! Now, open this file let’s start the actual coding!

Coding the Monty Hall Simulation

Let’s break down our simulation into manageable steps:

  1. Model three doors
  2. Randomly place the car behind one door
  3. Simulate the player’s initial choice
  4. Simulate Monty opening a door with a goat
  5. Simulate choosing the remaining door when the player decides to switch
  6. Calculate wins for both strategies: switching and staying

Let’s introduce a constant for the doors count so we won’t have the magic number 3 in our code.

const DOORS_COUNT = 3;
Enter fullscreen mode Exit fullscreen mode

We’ll keep the win numbers in respective variables:

let winsWithoutDoorChange = 0;
let winsWithDoorChange = 0;
Enter fullscreen mode Exit fullscreen mode

Let’s create a function that randomly generates an integer between 0 and given maxNumber:

const generateRandomNumber = (maxNumber) => {
  return Math.floor(Math.random() * maxNumber);
}
Enter fullscreen mode Exit fullscreen mode

We have 3 doors, starting from index with 0, so maxNumber will be 2. Let’s randomly select our door with car and the one the player chose:

const doorWithCar = generateRandomNumber(DOORS_COUNT);
const chosenDoor = generateRandomNumber(DOORS_COUNT);
Enter fullscreen mode Exit fullscreen mode

Then, we need to choose some door that the host will open. It must not be the one the player chose, and also must not be one with car. We can do that with this code (one of rare cases when do/while is actually appropriate):

do {
  openDoorWithGoat = generateRandomNumber(DOORS_COUNT);
} while ([chosenDoor, doorWithCar].includes(openDoorWithGoat));
Enter fullscreen mode Exit fullscreen mode

Ok, now we have one door chosen by player and another open door with a goat. The player can change their decision and choose the last door. Let’s simulate it:

const newChosenDoor = [0, 1, 2]
      .find(door => ![chosenDoor, openDoorWithGoat].includes(door));
Enter fullscreen mode Exit fullscreen mode

Here we iterate over an array of 3 elements (doors), and select the only one remaining (the door that is not selected and is not open). This is the new door that the player chooses.

All that remains is to check whether the player has won and increase the corresponding counter:

if (chosenDoor === doorWithCar) {
  winsWithoutDoorChange++;
}

if (newChosenDoor === doorWithCar) {
  winsWithDoorChange++;
}
Enter fullscreen mode Exit fullscreen mode

That’s it! Let’s put this logic in a for loop and try iterating with different numbers. Remember, the more iterations, the more accurate the final result will be.

Here’s the complete code for our simulation:

const ATTEMPTS_COUNT = 1000_000;
const DOORS_COUNT = 3;

const generateRandomNumber = (maxNumber) => {
  return Math.floor(Math.random() * maxNumber);
}

const simulateMontyHall = (attempts) => {
  let winsWithoutDoorChange = 0;
  let winsWithDoorChange = 0;

  for (let i = 0; i < attempts; i++) {
    const doorWithCar = generateRandomNumber(DOORS_COUNT);
    const chosenDoor = generateRandomNumber(DOORS_COUNT);

    let openDoorWithGoat;

    do {
      openDoorWithGoat = generateRandomNumber(DOORS_COUNT);
    } while ([chosenDoor, doorWithCar].includes(openDoorWithGoat));

    const newChosenDoor = [0, 1, 2]
      .find(door => ![chosenDoor, openDoorWithGoat].includes(door));

    if (chosenDoor === doorWithCar) {
      winsWithoutDoorChange++;
    }

    if (newChosenDoor === doorWithCar) {
      winsWithDoorChange++;
    }
  }

  return {
    winsWithoutDoorChange,
    winsWithDoorChange,
  }
}

const {
  winsWithoutDoorChange,
  winsWithDoorChange,
} = simulateMontyHall(ATTEMPTS_COUNT);

const withoutChangeWinProbability = (winsWithoutDoorChange / ATTEMPTS_COUNT * 100).toFixed(2);
const withChangeWinProbability = (winsWithDoorChange / ATTEMPTS_COUNT * 100).toFixed(2);

console.log(
  `Without change, won ${winsWithoutDoorChange} out of ${ATTEMPTS_COUNT} attempts. Probability is ${withoutChangeWinProbability}%`,
);
console.log(
  `With change, won ${winsWithDoorChange} out of ${ATTEMPTS_COUNT} attempts. Probability is ${withChangeWinProbability}%`,
);
Enter fullscreen mode Exit fullscreen mode

To start the program, simply run node index.js in terminal. You will have ~33.3% of wins if the player doesn’t change their initial choice, and ~66.6% of wins in case of change.

If you don’t want to create and run the program locally, here is a link to Codepen. Run it and check the results.

Hope you enjoyed it! If you have any notes, remarks or questions, please share them in the comments.

Prefer watching instead? Check out the video on YouTube.

Stay updated with the latest JavaScript and software development news! Join my Telegram channel for more insights and discussions: TechSavvy: Frontend & Backend.

. . .
Terabox Video Player