Last active
December 23, 2017 02:17
-
-
Save shreve/4a9e161a058c321538e00855d0dae126 to your computer and use it in GitHub Desktop.
The Monty Hall Problem
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| # Simulation of the Monty Hall problem | |
| # | |
| # In a given game, there are three doors with a prize behind one. | |
| # The player picks one of the doors. | |
| # Monty removes one of the non-selected doors that isn't the prize door. | |
| # There are now two doors left in play, and one contains a prize. | |
| # Monty asks the player if they'd like to switch doors. | |
| # | |
| # What should the player do? What is the probability the player will win if | |
| # they switch doors vs staying the same? | |
| # | |
| # The program randomly simulates the results of many rounds of the game to see | |
| # what the probabilities are like. | |
| # | |
| # Game | |
| # | |
| # This class is responsible for selecting the doors and detecting if the game | |
| # was won by the player. | |
| # | |
| class Game | |
| def initialize | |
| won? | |
| end | |
| # Compare the prize door to either the new door or original door depending on | |
| # whether the player switched or not. | |
| def won? | |
| if switched? | |
| new_door == prize_door | |
| else | |
| original_door == prize_door | |
| end | |
| end | |
| def switched? | |
| defined?(@sw) ? @sw : @sw = [true, false].sample | |
| end | |
| def original_door | |
| @od ||= random_door | |
| end | |
| def prize_door | |
| @pd ||= random_door | |
| end | |
| def new_door | |
| @nd ||= begin | |
| # The new door cannot be the original door | |
| doors = [0, 1, 2] - [original_door] | |
| # Remove one of the doors that isn't the original or prize door. | |
| doors -= ([0, 1, 2] - [original_door, prize_door]) | |
| # Pick one of the remaining doors | |
| doors.sample | |
| end | |
| end | |
| def random_door | |
| rand(3) | |
| end | |
| def inspect | |
| "[ #{door_ind(0)} ][ #{door_ind(1)} ][ #{door_ind(2)} ] #{'Won!' if won?}" | |
| end | |
| def to_s | |
| inspect | |
| end | |
| private | |
| def door_ind(index) | |
| i = '' | |
| i << 'O' if index == original_door | |
| i << 'N' if siwtched? && index == new_door | |
| i << 'P' if index == prize_door | |
| i | |
| end | |
| end | |
| def print_report(set) | |
| won = set.select(&:won?).count | |
| puts "total: #{set.count}" | |
| puts "won: #{won} (#{(won.to_f / set.count * 100).round(1)}%)" | |
| puts '' | |
| end | |
| games = Array.new(10_000).map { Game.new } | |
| switched = games.select(&:switched?) | |
| stayed = games - switched | |
| puts 'Switched' | |
| puts print_report(switched) | |
| puts 'Stayed' | |
| puts print_report(stayed) | |
| # The expected output reads something like the following | |
| # | |
| # Switched | |
| # total: 5065 | |
| # won: 3372 (66.6%) | |
| # | |
| # Stayed | |
| # total: 4935 | |
| # won: 1656 (33.6%) | |
| # | |
| # This may be a surprising result, that switching your door more likely leads | |
| # to a win, however this is normal probabilities. | |
| # | |
| # An intuitive explanation is that switching wins if you picked a bad door. | |
| # It's more likely that you picked a bad door than the right one, so it's more | |
| # likely that switching will win. |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment