Monty Hall with a billion doors

In order to provide intuition behind the solution of the Monty Hall problem, Antonio Cangiano says:

If there were a billion doors, you picked one, and then Monty proceeded to open up all the remaining doors but one, we’d have a situation where it would be extremely unlikely that you picked the right door at the beginning, while it would be extremely likely that the remaining door was the one that was concealing the car.

Now, what happens when there are more than three doors. In this post, I will modify the solution of my last post to work for any number of doors. It requires a little change to the program.

 import Data.List (delete, (\\) )
 import Text.Printf (printf)
 import Control.Monad
 import Control.Monad.MC

This time, instead of defining Door by listing all alternatives, I define it as an instance of Bounded class.

 data Door   = Door Int deriving (Show, Eq)
 numDoors    = 3

 instance Bounded Door where
   minBound = Door 1
   maxBound = Door numDoors

 instance Enum Door where
   toEnum      n     = Door n
   fromEnum (Door n) =    n

 doors = [minBound .. maxBound] :: [Door]

Object are the same as before.

 data Object = Car | Goat deriving (Show, Eq)
 type Universe = [Object]

There is one car; all other doors have goats. This can still be generated using the shuffle function.

 nature :: MC Universe
 nature = shuffle numDoors (Car: repeat Goat)

The contestant open one door at random.

 contestant :: MC Door
 contestant = sample numDoors doors

The options available to the host remain the same as before.

 options :: Universe -> Door -> [Door]
 options universe door = filter (\d -> Goat == open universe d) remainder
   where remainder = delete door doors

We need a generic function to see what is behind a closed door.

 open :: Universe -> Door -> Object
 open universe (Door n) = universe !! (n-1)

The host opens all but one door. We can do this by replacing the sample function with sampleSubset function.

 host :: [Door]-> MC [Door]
 host o = sampleSubset (numDoors-2) l o where l = length o

The strategies are now whether to stick or switch based on the door that the contestant chose, and the doors that the host opened.

 strategyStick :: Door -> [Door] -> Door
 strategyStick d1 d2 = d1

 strategySwitch :: Door -> [Door] -> Door
 strategySwitch d1 d2 = head (doors \\ (d1:d2))

The reward function is same as before.

 reward :: Universe -> Door -> Double
 reward u d = if Car == open u d then 1.0 else 0.0

And so is the generation of the ranom experiment.

 randomVariable :: (Door -> [Door] -> Door) -> MC Double
 randomVariable strategy = do
   u <- nature
   c <- contestant
   h <- host (options u c)
   let r = reward u (strategy c h)
   return r

And we see the result.

 main = let
   n     = 100000
   seed  = 42
   stats = repeatMC n (randomVariable strategyStick) `evalMC` mt19937 seed
   in do
      putStrLn $ printf "\nnumDoors                : %d" numDoors
      putStrLn $ printf "Mean                    : %f" (sampleMean stats)
      putStrLn $ printf "99%% Confidence interval : (%f, %f)"
                `uncurry` (sampleCI 0.99 stats)

Now lets see the results. For

numDoors                : 3
Mean                    : 0.3334800000000033
99% Confidence interval : (0.3296397390134338, 0.33732026098657275)

numDoors                : 30
Mean                    : 0.03466999999999957
99% Confidence interval : (0.03317983597888913, 0.03616016402111001)

numDoors                : 300
Mean                    : 0.0038399999999999784
99% Confidence interval : (0.0033362101507491866, 0.00434378984925077)

Well, I think that you get the idea. I am not going to run this thing for a billion doors.


3 thoughts on “Monty Hall with a billion doors

  1. As far as I can tell, this code is wrong. You do not take a samplesubset in such a way to exclude the car from being behind one of the doors that is opened. In this case, it is obvious your mean scales down directly with your numDoors size.

    • Cristophone: I think that I am taking care of excluding the door which has the car. The host function is called on options u c where options function filters all doors that have a Goat behind them, thus excluding the Car. So, I think that I am taking care of the Car unless, I overlooked something really simple.

  2. Pingback: Assertions in Haskell « Random Determinism

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )


Connecting to %s