Skip to content

Instantly share code, notes, and snippets.

@HirotoShioi
Last active August 29, 2018 02:27
Show Gist options
  • Save HirotoShioi/fd9765038eda6ece9519ce641443e23e to your computer and use it in GitHub Desktop.
Save HirotoShioi/fd9765038eda6ece9519ce641443e23e to your computer and use it in GitHub Desktop.
[小ネタ] Haskellでモンティ・ホール問題を解いてみよう ref: https://qiita.com/HirotoShioi/items/b64198dd346d178b73fb
module Lib
( montyHall
, runMontyHall
) where
import Control.Monad (replicateM)
import Data.Semigroup ((<>))
import System.Random (randomRIO)
-- | Given an list, picks an element
pick :: [a] -> IO a
pick xs = do
ele <- randomRIO (0, length xs - 1)
return $ xs !! ele
-- | Prizes from Monty Hall
data Prize =
Goat
| Car
deriving (Eq, Show)
-- | Run monty hall
montyHall :: IO Bool
montyHall = do
prize <- pick [[Car, Goat, Goat], [Goat, Car, Goat], [Goat, Goat, Car]]
choose <- pick [0 .. 2]
monty <- pick [ i | i <- [0 .. 2], i /= choose, prize !! i == Goat ]
let switch = head [ i | i <- [0 .. 2], i /= choose, i /= monty ]
return $ prize !! switch == Car
-- | Run @'montyHall'@ given number of times and compute it's winning percentage
runMontyHall :: Int -> IO ()
runMontyHall num = do
putStrLn $ "Running monty hall " <> show num <> " times"
-- Run the computation
xs <- replicateM num montyHall
let winning = filter (== True) xs
-- Compute the winning percentage
let winningPercentage = fromIntegral (length winning) / fromIntegral num * 1000
let winningPercentageRound = fromIntegral (ceiling winningPercentage) / 10
-- Print the results
putStrLn "Computation is done!"
putStrLn $ "Chance of winning a car is " <> show winningPercentageRound <> "%"
*Main Lib> runMontyHall 100000
Running monty hall 100000 times
Computation is done!
Chance of winning a car is 66.7%
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment