Powered by AppSignal & Oban Pro
Would you like to see your link here? Contact us

Monty Hall

monty_hall_problem.livemd

Monty Hall

Mix.install([
  {:vega_lite, "~> 0.1.4"},
  {:kino_vega_lite, "~> 0.1.1"}
])

alias VegaLite, as: Vl

Code used

A simulation of the Monty Hall problem, or an excuse to play with Livebooks. See below.

defmodule Monty do
  def choice(), do: Enum.random(0..2)

  def monty(correct_door, my_choice, action, monty_sees?) do
    doors =
      HashSet.new()
      |> HashSet.put(0)
      |> HashSet.put(1)
      |> HashSet.put(2)

    montys_choice =
      case monty_sees? do
        true ->
          doors
          |> HashSet.delete(my_choice)
          |> HashSet.delete(correct_door)

        false ->
          doors
          |> HashSet.delete(my_choice)
      end
      |> Enum.shuffle()
      |> List.first()

    other_door =
      doors
      |> HashSet.delete(my_choice)
      |> HashSet.delete(montys_choice)
      |> HashSet.to_list()
      |> List.first()

    # IO.puts("Right door is #{right_door} - You choose #{my_choice} - Monty chooses #{montys_choice} - Updated choice is #{other_door} " )

    case action do
      :keep -> my_choice == correct_door
      :switch -> other_door == correct_door
    end
  end

  def monty(mode, monty_sees?),
    do: monty(choice(), choice(), mode, monty_sees?)

  def monty_freqs(mode, monty_sees?, n),
    do:
      Enum.map(0..n, fn _hit ->
        Monty.monty(mode, monty_sees?)
      end)
      |> Enum.frequencies()

  def freq_plot(frequencies) do
    data = [
      %{"Outcome" => "Success", "n" => frequencies[true]},
      %{"Outcome" => "Loss", "n" => frequencies[false]}
    ]

    Vl.new(width: 400, height: 300)
    |> Vl.data_from_values(data)
    |> Vl.mark(:bar)
    |> Vl.encode_field(:x, "Outcome", type: :nominal, axis: [label_angle: 0])
    |> Vl.encode_field(:y, "n", type: :quantitative)
  end
end

The Monty Hall problem - should you switch?

Suppose you’re on a game show, and you’re given the choice of three doors: Behind one door is a car; behind the others, goats. You pick a door, say No. 1, and the host, who knows what’s behind the doors, opens another door, say No. 3, which has a goat. He then says to you, “Do you want to pick door No. 2?” Is it to your advantage to switch your choice?

If we don’t switch (we stick to our choice) we intuitively know we have 1/3 of hits - let’s see if the simulation is consistent.

Monty.monty_freqs(:keep, true, 10000)
|> Monty.freq_plot()

But - if we switch, we have a 2/3 chance of winning!

Monty.monty_freqs(:switch, true, 10000)
|> Monty.freq_plot()

But - where does this result come from? it comes from information that Monty has.

We can easily see this in action by imagining that Monty is drunk, so he does not see which door has a hidden prize and choses one at random. In this case, keeping or switching makes no difference.

Monty.monty_freqs(:keep, false, 10000)
|> Monty.freq_plot()
Monty.monty_freqs(:switch, false, 10000)
|> Monty.freq_plot()