import Data.Function (on) import Data.List import Data.Char data Hand = C Int Int Int Int Int deriving (Eq, Show) instance Ord Hand where compare x y = let r = (compare `on` handType) x y f (C x1 x2 x3 x4 x5) = (x1, x2, x3, x4, x5) in case r of EQ -> (compare `on` f) x y _ -> r handType :: Hand -> Int handType (C x1 x2 x3 x4 x5) = case cList of [5] -> 7 [1, 4] -> 6 + signum j [2, 3] -> 4 + 3 * signum j [1, 1, 3] -> 3 + 3 * signum j [1, 2, 2] -> 2 + 2 * j [1, 1, 1, 2] -> 1 + 2 * signum j _ -> 0 + signum j where cList = sort $ map length $ group sList sList = sort [x1, x2, x3, x4, x5] j = length (filter (==1) sList) main :: IO () main = do input <- readFile "input" print $ day07 (parse False input) print $ day07 (parse True input) day07 :: [(Hand, Int)] -> Int day07 = sum . zipWith (*) [1..] . map snd . sort parse :: Bool -> String -> [(Hand, Int)] parse p2 = map (f . words) . lines where f [x,y] = (parseHand x, read y) f x = error ("parse: Malformed input: " ++ show x) parseHand = g . map (digitToCard p2) g [x1, x2, x3, x4, x5] = C x1 x2 x3 x4 x5 g x = error ("parseHand: Malformed input: " ++ show x) digitToCard :: Bool -> Char -> Int digitToCard p2 x | isDigit x = digitToInt x | x == 'J' && p2 = 1 | x == 'T' = 10 | x == 'J' = 11 | x == 'Q' = 12 | x == 'K' = 13 | x == 'A' = 14 | otherwise = error ("digitToCard: Malformed input: " ++ show x)