Thursday, January 15, 2009

They see me rollin': a probability problem

Say you're playing 7-card stud and are dealt rolled-up deuces. If you see the case deuce as someone else's door, what is the probability that you'll bring it in?

In stud high games, the player with the lowest upcard is the bring-in. Suits break ties, with different places using different orders, so let's use bridge order, i.e., clubs, diamonds, hearts, and spades. Deuce of clubs always pays the bring-in.

The search space is small enough to use brute force. Front matter first:

> import Control.Monad
> import qualified System.IO.UTF8 as UTF8
> import Text.Printf
Modeling suits is straightforward:
> data Suit = C | D | H | S deriving (Show, Ord, Eq, Enum)
Haskell's deriving clause saves tedious definitions. For example, making Suit an instance of the Ord typeclass means that clubs are less than diamonds and so on.

We walk through all possibilities and report the probability:

> main = do
>   mapM_ display doors
>   putStrLn $ printf "Hero bringin probability: %.3f%%"
>                     (100.0 * k / n :: Float)

Simulate the deal. Automatically deriving an instance of the Enum typeclass allows us to use shorthand for all suits. From the problem statement, we know our hero will see two deuces, and the others are in the hole. Enumerating all possibilities is trivial with a list comprehension.

>   where doors = deal [C .. S]
>         deal xs = [ (h,v) | h <- xs, v <- xs, h /= v ]

Here we apply the definition of probability: the ratio of the number of times an event occurs with the total number of events:

>         hero  = [1.0 | (h,v) <- doors, h < v ]
>         (k,n) = (sum hero, fromIntegral $ length doors)

Given a pair of hero and villain door cards, pretty-print it to the standard output:

> display (h,v) = UTF8.putStrLn bringin
>   where hv = "Hero: " ++ (suit h) ++ ", Villain: " ++ (suit v)
>         bringin | h < v     = hv ++ " *"
>                 | otherwise = hv
>         suit C = "♣"
>         suit D = "♦"
>         suit H = "♥"
>         suit S = "♠"

Output:

Hero: ♣, Villain: ♦ *
Hero: ♣, Villain: ♥ *
Hero: ♣, Villain: ♠ *
Hero: ♦, Villain: ♣
Hero: ♦, Villain: ♥ *
Hero: ♦, Villain: ♠ *
Hero: ♥, Villain: ♣
Hero: ♥, Villain: ♦
Hero: ♥, Villain: ♠ *
Hero: ♠, Villain: ♣
Hero: ♠, Villain: ♦
Hero: ♠, Villain: ♥
Hero bringin probability: 50.000%

No comments: