Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- import Data.Char
- import Data.Ord
- import Data.List
- import Data.Maybe
- import Data.Function
- data Suit = C | S | D | H
- deriving (Show, Read, Eq, Ord)
- newtype Rank = Rank Int
- deriving (Eq, Ord)
- instance Show Rank where
- show (Rank 10) = "T"
- show (Rank 11) = "J"
- show (Rank 12) = "Q"
- show (Rank 13) = "K"
- show (Rank 14) = "A"
- show (Rank n) = show n
- instance Read Rank where
- readsPrec _ ('T':r) = [(Rank 10, r)]
- readsPrec _ ('J':r) = [(Rank 11, r)]
- readsPrec _ ('Q':r) = [(Rank 12, r)]
- readsPrec _ ('K':r) = [(Rank 13, r)]
- readsPrec _ ('A':r) = [(Rank 14, r)]
- readsPrec _ (d:r) | isDigit d = [(Rank $ digitToInt d, r)]
- | otherwise = error "Wrong rank"
- type Card = (Rank, Suit)
- readCard :: String -> Card
- readCard (r:s:[]) = (read [r], read [s])
- readCard _ = error "Wrong card"
- getRank = fst
- getSuit = snd
- type SortedHand = [Card]
- readHand = sortHand . map readCard . words
- data PokerHand = Kicker Rank
- | Pair Rank
- | TwoPairs Rank Rank
- | ThreeOfAKind Rank
- | Straight Rank
- | Flush [Rank]
- | FullHouse Rank Rank
- | FourOfAKind Rank
- | StraightFlush Rank
- deriving (Eq, Ord, Show)
- checkCombos hand = catMaybes $ map (\f -> f hand) [hasKicker, hasPair, hasTwoPairs, hasThreeOfAKind, hasStraight, hasFlush, hasFullHouse]
- type CheckHand = SortedHand -> Maybe PokerHand
- down LT = GT
- down EQ = EQ
- down GT = LT
- sortHand :: SortedHand -> SortedHand
- sortHand = reverse . sortBy (comparing getRank)
- getGroupRank = getRank . head
- hasKicker :: CheckHand
- hasKicker = Just . Kicker . getGroupRank
- groupRanks = reverse . sortBy (comparing length) . groupBy ((==) `on` getRank)
- hasPair :: CheckHand
- hasPair hand = find (\g -> length g >= 2) (groupRanks hand) >>= return . Pair . getGroupRank
- hasTwoPairs :: CheckHand
- hasTwoPairs hand = case filter (\g -> length g >= 2) (groupRanks hand) of
- (g1:g2:_) -> Just $ TwoPairs (getGroupRank g1) (getGroupRank g2)
- _ -> Nothing
- hasThreeOfAKind :: CheckHand
- hasThreeOfAKind hand = find (\g -> length g >= 3) (groupRanks hand) >>= return . ThreeOfAKind . getGroupRank
- hasStraight :: CheckHand
- hasStraight hand = findStraight (zipWith (\a b -> (diffRank a b, a)) ranks (tail ranks))
- where ranks = nub $ map getRank hand
- diffRank (Rank a) (Rank b) = a - b
- findStraight ((1, f):(1, _):(1, _):(1, _):_) = Just $ Straight f
- findStraight (x:xs) = findStraight xs
- findStraight _ = Nothing
- hasFlush :: CheckHand
- hasFlush hand = find (\g -> length g >= 5) [filter (\c -> getSuit c == s) hand | s <- [C, S, D, H]] >>= return . Flush . map getRank
- hasFullHouse :: CheckHand
- hasFullHouse hand = findFullHouse $ groupRanks hand
- where findFullHouse ((c11:c12:c13:_):(c21:c22:_):_) = Just $ FullHouse (getRank c11) (getRank c21)
- findFullHouse (x:xs) = findFullHouse xs
- findFullHouse _ = Nothing
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement