2023-12-07 14:04:36 +01:00
import Data.Char
2023-12-07 13:04:59 +01:00
import Data.Function ( on )
import Data.List
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
2023-12-07 13:57:43 +01:00
[ 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
2023-12-07 13:04:59 +01:00
where
2023-12-07 13:57:43 +01:00
cList = sort $ map length $ group sList
sList = sort [ x1 , x2 , x3 , x4 , x5 ]
2023-12-07 14:04:36 +01:00
j = length ( filter ( == 1 ) sList )
2023-12-07 13:04:59 +01:00
main :: IO ()
main = do
2023-12-07 13:57:43 +01:00
input <- readFile " input "
print $ day07 ( parse False input )
print $ day07 ( parse True input )
2023-12-07 13:04:59 +01:00
2023-12-07 13:57:43 +01:00
day07 :: [ ( Hand , Int ) ] -> Int
2023-12-07 14:04:36 +01:00
day07 = sum . zipWith ( * ) [ 1 .. ] . map snd . sort
2023-12-07 13:04:59 +01:00
2023-12-07 13:57:43 +01:00
parse :: Bool -> String -> [ ( Hand , Int ) ]
parse p2 = map ( f . words ) . lines
2023-12-07 14:04:36 +01:00
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 )
2023-12-07 13:04:59 +01:00
2023-12-07 13:57:43 +01:00
digitToCard :: Bool -> Char -> Int
digitToCard p2 x
2023-12-07 13:04:59 +01:00
| isDigit x = digitToInt x
2023-12-07 13:57:43 +01:00
| x == 'J' && p2 = 1
2023-12-07 13:04:59 +01:00
| x == 'T' = 10
| x == 'J' = 11
| x == 'Q' = 12
| x == 'K' = 13
| x == 'A' = 14
| otherwise = error ( " digitToCard: Malformed input: " ++ show x )