The file, poker.txt, contains one-thousand random hands dealt to two players. Each line of the file contains ten cards (separated by a single space): the first five are Player 1's cards and the last five are Player 2's cards. You can assume that all hands are valid (no invalid characters or repeated cards), each player's hand is in no specific order, and in each hand there is a clear winner.
How many hands does Player 1 win?
The file, poker.txt, contains one-thousand random hands dealt to two players. Each line of the file contains ten cards (separated by a single space): the first five are Player 1's cards and the last five are Player 2's cards. You can assume that all hands are valid (no invalid characters or repeated cards), each player's hand is in no specific order, and in each hand there is a clear winner.
How many hands does Player 1 win?
The file, poker.txt, contains one-thousand random hands dealt to two players. Each line of the file contains ten cards (separated by a single space): the first five are Player 1's cards and the last five are Player 2's cards. You can assume that all hands are valid (no invalid characters or repeated cards), each player's hand is in no specific order, and in each hand there is a clear winner.
How many hands does Player 1 win?
import Data.Monoid(mappend)
import Data.List(sortBy, sort, group, nub, elemIndex)
import Control.Arrow((&&&), (***))
import Data.Maybe(fromJust)
import Control.Monad(join)
type Hand = String
type Values = [Int]
data Ranking = HighCard | Pair | TwoPair | ThreeOfAKind | Straight | Flush | FullHouse | FourOfAKind | StraightFlush deriving (Eq, Ord)
data HandValue = HandValue Ranking Values
instance Eq HandValue where
HandValue r1 v1 == HandValue r2 v2 = r1 == r2 && v1 == v2
instance Ord HandValue where
HandValue r1 v1 `compare` HandValue r2 v2 = (r1 `compare` r2) `mappend` (v1 `compare` v2)
rateHand :: Hand -> HandValue
rateHand hand
| straight && flush = HandValue StraightFlush ranks
| flush = HandValue Flush ranks
| straight = HandValue Straight ranks
| otherwise = case map fst groups of
[4, 1] -> HandValue FourOfAKind values
[3, 2] -> HandValue FullHouse values
[3, 1, 1] -> HandValue ThreeOfAKind values
[2, 2, 1] -> HandValue TwoPair values
[2, 1, 1, 1] -> HandValue Pair values
otherwise -> HandValue HighCard values
where
sf = (`elem` "SCDH")
ranks = sortBy (flip compare) $ map (fromJust . (`elemIndex` "23456789TJQKA")) $ filter (not . sf) hand
suits = filter sf hand
flush = length (nub suits) == 1
straight = straight = ranks == reverse [last ranks..head ranks] || ranks == [12,3,2,1,0]
groups = sortBy descSort . map (length &&& id) $ group ranks
values = concatMap snd groups
descSort (l1,v1) (l2,v2) = (l2 `compare` l1) `mappend` (v2 `compare` v1)
parseLine :: String -> Bool
parseLine line = uncurry (>) $ join (***) rateHand $ splitAt 10 $ filter (/= ' ') line
main :: IO ()
main = do
pots <- lines <$> readFile "p054_poker.txt"
print $ length $ filter parseLine pots
import Data.Monoid(mappend)
import Data.List(sortBy, sort, group, nub, elemIndex)
import Control.Arrow((&&&), (***))
import Data.Maybe(fromJust)
import Control.Monad(join)
type Hand = String
type Values = [Int]
data Ranking = HighCard | Pair | TwoPair | ThreeOfAKind | Straight | Flush | FullHouse | FourOfAKind | StraightFlush deriving (Eq, Ord)
data HandValue = HandValue Ranking Values
instance Eq HandValue where
HandValue r1 v1 == HandValue r2 v2 = r1 == r2 && v1 == v2
instance Ord HandValue where
HandValue r1 v1 `compare` HandValue r2 v2 = (r1 `compare` r2) `mappend` (v1 `compare` v2)
rateHand :: Hand -> HandValue
rateHand hand
| straight && flush = HandValue StraightFlush ranks
| flush = HandValue Flush ranks
| straight = HandValue Straight ranks
| otherwise = case map fst groups of
[4, 1] -> HandValue FourOfAKind values
[3, 2] -> HandValue FullHouse values
[3, 1, 1] -> HandValue ThreeOfAKind values
[2, 2, 1] -> HandValue TwoPair values
[2, 1, 1, 1] -> HandValue Pair values
otherwise -> HandValue HighCard values
where
sf = (`elem` "SCDH")
ranks = sortBy (flip compare) $ map (fromJust . (`elemIndex` "23456789TJQKA")) $ filter (not . sf) hand
suits = filter sf hand
flush = length (nub suits) == 1
straight = straight = ranks == reverse [last ranks..head ranks] || ranks == [12,3,2,1,0]
groups = sortBy descSort . map (length &&& id) $ group ranks
values = concatMap snd groups
descSort (l1,v1) (l2,v2) = (l2 `compare` l1) `mappend` (v2 `compare` v1)
parseLine :: String -> Bool
parseLine line = uncurry (>) $ join (***) rateHand $ splitAt 10 $ filter (/= ' ') line
main :: IO ()
main = do
pots <- lines <$> readFile "p054_poker.txt"
print $ length $ filter parseLine pots
import Data.Monoid(mappend)
import Data.List(sortBy, sort, group, nub, elemIndex)
import Control.Arrow((&&&), (***))
import Data.Maybe(fromJust)
import Control.Monad(join)
type Hand = String
type Values = [Int]
data Ranking = HighCard | Pair | TwoPair | ThreeOfAKind | Straight | Flush | FullHouse | FourOfAKind | StraightFlush deriving (Eq, Ord)
data HandValue = HandValue Ranking Values
instance Eq HandValue where
HandValue r1 v1 == HandValue r2 v2 = r1 == r2 && v1 == v2
instance Ord HandValue where
HandValue r1 v1 `compare` HandValue r2 v2 = (r1 `compare` r2) `mappend` (v1 `compare` v2)
rateHand :: Hand -> HandValue
rateHand hand
| straight && flush = HandValue StraightFlush ranks
| flush = HandValue Flush ranks
| straight = HandValue Straight ranks
| otherwise = case map fst groups of
[4, 1] -> HandValue FourOfAKind values
[3, 2] -> HandValue FullHouse values
[3, 1, 1] -> HandValue ThreeOfAKind values
[2, 2, 1] -> HandValue TwoPair values
[2, 1, 1, 1] -> HandValue Pair values
otherwise -> HandValue HighCard values
where
sf = (`elem` "SCDH")
ranks = sortBy (flip compare) $ map (fromJust . (`elemIndex` "23456789TJQKA")) $ filter (not . sf) hand
suits = filter sf hand
flush = length (nub suits) == 1
straight = ranks == reverse [last ranks..head ranks] || ranks == [12,3,2,1,0]
groups = sortBy descSort . map (length &&& id) $ group ranks
values = concatMap snd groups
descSort (l1,v1) (l2,v2) = (l2 `compare` l1) `mappend` (v2 `compare` v1)
parseLine :: String -> Bool
parseLine line = uncurry (>) $ join (***) rateHand $ splitAt 10 $ filter (/= ' ') line
main :: IO ()
main = do
pots <- lines <$> readFile "p054_poker.txt"
print $ length $ filter parseLine pots
My implementation works perfectly and is very fast (100,000 lines in 10 sec in ghci, actual problem is instant), so I'm not necessarily looking for performance improvements; any kind of feedback is more than welcome.
My implementation works perfectly and is very fast, so I'm not necessarily looking for performance improvements; any kind of feedback is more than welcome.
My implementation works perfectly and is very fast (100,000 lines in 10 sec in ghci, actual problem is instant), so I'm not necessarily looking for performance improvements; any kind of feedback is more than welcome.