ポーカーの役判定
最近ちょっとHaskellやる気が出てきたので、昨日の(どう書く?orgの)Ruby版をベースにHaskellで書いてみました。ふつけるの第8章までに登場するもの以外は、たぶんほとんど使っていません。
自分のHaskell力では、今のところこれが精一杯かな。なので、あまりきれいとは言えないコードですが、この状態で上げてしまいます。
import System import List import Char main = getArgs >>= print . pokerHand . head pokerHand :: String -> String pokerHand s -- cards | isFlush s && isRoyalStraight s = "Royal Flush" | isFlush s && isStraight s = "Straight Flush" | isFlush s = "Flush" | isStraight s = "Straight" | includeNLength s 4 = "Four of a kind" | all (includeNLength s) [2, 3] = "Full house" | includeNLength s 3 = "Three of a kind" | includeNLength s 2 && (length . group . toNumbers) s == 3 = "Two pair" | includeNLength s 2 = "One Pair" | otherwise = "No Pair" includeNLength :: String -> Int -> Bool includeNLength cards n = any (\i -> length i == n) $ group $ toNumbers cards isRoyalStraight :: String -> Bool isRoyalStraight cards = sort (toNumbers cards) == [1, 10, 11, 12, 13] isFlush :: String -> Bool isFlush cards = (length . group . toSuits) cards == 1 isStraight :: String -> Bool isStraight cards = any (\i -> take 5 i == toNumbers cards) $ tails [1..13] toSuits :: String -> String toSuits cards = [snd x | x <- filter (\i -> even $ fst i) $ zip [0..] cards] toNumbers :: String -> [Int] toNumbers cards = sort [ rankToInt(snd x) | x <- filter (\i -> odd $ fst i) $ zip [0..] cards] rankToInt :: Char -> Int rankToInt rank | rank == 'A' = 1 | rank == 'T' = 10 | rank == 'J' = 11 | rank == 'Q' = 12 | rank == 'K' = 13 | isDigit rank = ord rank - 48 | otherwise = 0