Simulation

< Code In The Browser

For this section we use loops to run little random scenarios -- like flipping a coin -- thousands of times to see what outcomes we get. In this way, the computer works as a sort of telescope, giving us insight about the space of outcomes but without requiring us to do any any formal mathematics. Just run the simulation and see what it does! This is also known as "monte carlo simulation".

For the simulation code, the function call random(1, 6) returns a random number in between the two numbers (inclusive), so the result of random(1, 6) is like rolling a 6-sided die, and random(1, 2) is like flipping a coin.

The strategy will have an outer loop to run, say, 1000 trials. Inside the loop we have the code to run one trial. The function series(1000) returns a collection of the numbers 1, 2, 3... 1000. Using this, we can write a loop to iterate 1000 (or whatever number) times, like this

for (i: series(1000)) {
  ...
}

To record what happens, we'll use the Histogram(min, max) class. Use histogram.add(val) to record one trial value, and print(histogram) to print its current state. The following code example demonstrates the use of all these functions:

Pair Of dice

Here we'll simulate rolling a pair or 6-sided dice, keeping track of what numbers we get. So one trial = roll a pair of 6 sided dice. How often should a 7 appear (aka the ideal "expected" result)? How often should a 2 appear?


Mathematically, the 7 should appear 1/7 of the time. As then number of trials gets larger (100, 1000, 10000), note how the simulation produces a count which gets closer to the mathematically expected result.

Head Count

Trial = flip a coin 10 times, count the number of heads. Here we use a second, nested loop to flip a coin 10 times, counting the number of times that heads comes up.


Heads In A Row

Trial = flip coin 10 times, but stop on the first tails. How many heads in a row? ("break:" is a command to immediately exit the current loop.)


Roulette Exercise

Roulette -- the wheel with the little ball that falls into a slot, appearing in many movies (Roulette wikipedia). The slots are numbered 0..36. The simplest bet is to take 19..36 (or 1..18), which pays double if the ball falls in that range. If the ball falls in the 0 slot, then all players lose -- this provides the small house edge which is magnified greatly the more times the player plays. The effect of playing more and more times can be explored with the simulation.

Add code here so one trial is playing roulette with a starting balance of 10, betting 1 each time, and playing 50 rounds (or until out of money). For each trial, record the ending balance in the histogram. (Solution available.)


The code shows the range of outcomes playing roulette 50 times. What happens if the player plays 500 or 5000 times? Side question: if the player plays 10 times, there is an even/odd pattern in their possible balance. Why is this?

    // your code here
    if (bal == 0) {
      break;
    }
    bal = bal - 1;  // place the bet
    roll = random(0, 36);
    if (roll >= 19) { // get double back on win
      bal = bal + 2;
    }

Rickety Bridge Exercise

You are in a party of 6 on one side of a deep ravine. There is a rickety bridge across the ravine, but only one person can go across at a time. For the 1st person to go across, there is 1/6 chance of bridge collapse. For the 2nd person, a 2/6 chance of collapse, and so on. The 6th person has a 6/6 (100%) chance of collapse if they have to go. If the bridge collapses, nobody else has to go. If you want to avoid being on the bridge when it collapses, which person do you want to be?


What is the best person to be? It's harder to see which is the worst person to be, but it can be done with a large number of trials.

    // your code here
    roll = random(1, 6);
    if (roll <= j) { // bridge collapses for person j
      break;
    }

If you are interested in probability, it is also possible to work out the exact mathematics for each person. Construct a tree of the events. From the start position, there are two branches: a. person 1 bridge collapse (1/6), b. person 1 makes it across (5/6). Then extending from branch (b) there are two branches for person 2, and so on. For the probability of a particular outcome, work from the start, multiplying together the probabilities of each branch taken. Note that for each a/b branch, the probabilities add to 1 (either a or b happens). Working out just the first couple layers of the tree, you can check your math vs. the results of the simulation.

Monty Hall Problem

This is a very famous probability problem based on the Lets Make A Deal TV show. See Monty Hall Problem (wikipedia) for background. Provided for this problem is a neitherOfThese(a, b) function which given two numbers that are 1, 2, or 3, returns one of 1, 2, or 3 which is not equal to the two passed in numbers. This function is simple, but turns out to be very useful for the Monty Hall problem.

For the standard strategy, the player keeps their original pick, and so wins 1/3 of the time. The code below simulates the standard strategy. The "switch" strategy means the player changes their pick to the door which is not their original pick and is not the door revealed by Monty. Is the switch strategy superior? The reasoning is very unintuitive, however the simulation can quite clearly show the performance of both strategies. Add code below the standard strategy to implement/print the results of the switch strategy to answer this question.


  pick = neitherOfThese(pick, reveal);
  if (pick == good) {
    win2++;
  }

This work was created by Nick Parlante and is released under the Creative Commons Share-Alike license 3.0