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.
Posted by Christophe Poucet on January 30, 2009 at 1:33 pm
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.
Posted by randomdeterminism on January 30, 2009 at 8:07 pm
Cristophone: I think that I am taking care of excluding the door which has the car. The
hostfunction is called onoptions u cwhereoptionsfunction filters all doors that have aGoatbehind them, thus excluding theCar. So, I think that I am taking care of theCarunless, I overlooked something really simple.Posted by Assertions in Haskell « Random Determinism on February 1, 2009 at 1:51 pm
[...] in Haskell Jump to Comments Sometime back, I posted how to solve the Monty Hall problem with a million doors. Christophe Poucet wondered if I was [...]