Advertisement
Guest User

Untitled

a guest
Jul 30th, 2016
55
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 3.43 KB | None | 0 0
  1. import Control.Applicative
  2. import Control.Monad
  3. import Data.List
  4. import Data.Function (on)
  5. import Data.Ratio
  6. import Data.Char
  7.  
  8. newtype P a = P {probabilities :: [(Rational,a)] }
  9.  
  10. instance Functor P where
  11. fmap f (P a) = P ((fmap . fmap) f a)
  12.  
  13. instance Applicative P where
  14. pure = P . (:[]) . ((,) 1)
  15. P f <*> P a = P (filter ((/= 0) . fst) (do
  16. (pf,f') <- f
  17. (pa,a') <- pf `seq` a
  18. let pr = pf * pa in pr `seq` return (pr, f' a')
  19. ))
  20.  
  21. instance Monad P where
  22. return = pure
  23. P a >>= f = P (filter ((/= 0) . fst) (do
  24. (pa,a') <- a
  25. (pb,b') <- pa `seq` probabilities (f a')
  26. let pr = pa * pb in pr `seq` return (pr, b')
  27. ))
  28.  
  29. uniform l = let
  30. s = 1 % genericLength l
  31. in P $ map ((,) s) l
  32.  
  33. distributed :: (Real f) => [(f,a)] -> P a
  34. distributed l = let
  35. s = 1 / sum (map (toRational . fst) l)
  36. in P (map (\(r,a) -> (toRational r * s,a)) l)
  37.  
  38. collate :: (Eq a) => P a -> P a
  39. collate = P . go . probabilities where
  40. go :: Eq a => [(Rational,a)] -> [(Rational,a)]
  41. go [] = []
  42. go ((pa,a):r) = let
  43. (m,n) = partition ((== a) . snd) r
  44. in (pa + sum (map fst m), a) : go n
  45.  
  46. collate' :: (Ord a) => P a -> P a
  47. collate' = P .
  48. map (\((pa,a):r) -> (pa + sum (map fst r), a)) .
  49. groupBy ((==) `on` snd) .
  50. sortBy (compare `on` snd) .
  51. probabilities
  52.  
  53. select :: [a] -> [(a,[a])]
  54. select = go id where
  55. go _ [] = []
  56. go acc (a:r) = (a, acc r) : go (acc . (a :)) r
  57.  
  58. oneCard :: [(Integer,Integer,Integer)] -> P [(Integer,Integer,Integer)]
  59. oneCard l = collate' $ do
  60. ((h,s,n),r) <- distributed $
  61. map (\v@((_,s,n),_) -> (s * n, v)) $
  62. select l
  63. return $ sort $ case n of
  64. 1 -> (h + 1, s - 1, 1) : r
  65. _ -> (h + 1, s - 1, 1) : (h, s, n - 1) : r
  66.  
  67. oneHand :: [(Integer,Integer)] -> P (Integer,[(Integer,Integer)])
  68. oneHand l' = collate' $ do
  69. let l = map (\(s,n) -> (0,s,n)) l'
  70. l2 <- foldl' (\a _ -> collate $ a >>= oneCard) (return l) (replicate 5 ())
  71. let
  72. ri = if (sort $ filter (/= 0) $ map (\(a,_,_) -> a) l2) == [2,3]
  73. then 1
  74. else 0
  75. rl = map (\((s,n):r) -> (s,n + sum (map snd r))) $
  76. groupBy ((==) `on` fst) $
  77. sortBy (compare `on` fst) $
  78. filter (/= (0,0)) $
  79. map (\(_,s,n) -> (s,n)) l2
  80. return (ri,rl)
  81.  
  82. hands :: Integer -> [(Integer,Integer)] -> P Integer
  83. hands n = collate' . fmap fst . go . return . ((,) 0) where
  84. go = flip (foldl' (\s _ -> collate' $ s >>= \(f,d) -> do
  85. (i,r) <- oneHand d
  86. return (i + f, r)
  87. )) [1 .. n]
  88.  
  89. distribution :: [(Integer,Integer)] -> [P Integer]
  90. distribution d = let
  91. mp = (sum $ map (uncurry (*)) d) `div` 5
  92. in genericTake mp $
  93. tail $
  94. map (collate' . fmap fst) $
  95. iterate (\e -> collate' $
  96. e >>= \(f,d) -> do
  97. (i,r) <- oneHand d
  98. return (i + f, r)
  99. ) $
  100. return (0,d)
  101.  
  102. show3sf :: Rational -> String
  103. show3sf r = let
  104. w = floor r :: Integer
  105. m = r - toRational w
  106. sw = show w
  107. s0 = if w == 0 then 3 else max 1 (3 - length sw)
  108. go1 0 = "0"
  109. go1 m' = case floor m' of
  110. 0 -> '0' : go1 (m' * 10)
  111. d -> intToDigit d :
  112. go2 (s0 - 2) ((m' - toRational d) * 10)
  113. go2 _ 0 = "0"
  114. go2 0 m' = [intToDigit $ min 9 $ round m']
  115. go2 rd m' = let
  116. d = floor m'
  117. in intToDigit d : go2 (rd - 1) ((m' - toRational d) * 10)
  118. in sw ++ "." ++ case w of
  119. 0 -> go1 (m * 10)
  120. _ -> go2 (s0 - 1) (m * 10)
  121.  
  122. main = forM_ (zip [1..] $ distribution [(13,4)]) $ \(p,d) -> do
  123. putStrLn $ "Probability distribution for full houses: " ++ show p ++ " hands"
  124. forM_ (probabilities d) $ \(f,c) ->
  125. putStrLn $ show c ++ ": " ++ show3sf (f * 100) ++ "%"
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement