{-# Language QuasiQuotes, TransformListComp, ParallelListComp #-}
module Main (main) where
import Advent (format, counts)
import Data.Foldable (toList)
import Data.List (sortOn, sort, elemIndex, nub)
import Data.Maybe (fromJust)
main :: IO ()
IO ()
main =
do [([Char], Int)]
input <- [format|2023 7 (%s %d%n)*|]
Int -> IO ()
forall a. Show a => a -> IO ()
print (([Char] -> [Int]) -> [([Char], Int)] -> Int
forall a. Ord a => ([Char] -> a) -> [([Char], Int)] -> Int
winnings [Char] -> [Int]
strength1 [([Char], Int)]
input)
Int -> IO ()
forall a. Show a => a -> IO ()
print (([Char] -> [Int]) -> [([Char], Int)] -> Int
forall a. Ord a => ([Char] -> a) -> [([Char], Int)] -> Int
winnings [Char] -> [Int]
strength2 [([Char], Int)]
input)
winnings :: Ord a => (String -> a) -> [(String, Int)] -> Int
winnings :: forall a. Ord a => ([Char] -> a) -> [([Char], Int)] -> Int
winnings [Char] -> a
strength [([Char], Int)]
input =
[Int] -> Int
forall a. Num a => [a] -> a
forall (t :: * -> *) a. (Foldable t, Num a) => t a -> a
sum [Int
bid Int -> Int -> Int
forall a. Num a => a -> a -> a
* Int
rank | Int
rank <- [Int
1..]
| ([Char]
hand, Int
bid) <- [([Char], Int)]
input, then (a -> a) -> [a] -> [a]
(([Char], Int) -> a) -> [([Char], Int)] -> [([Char], Int)]
forall {a}. (a -> a) -> [a] -> [a]
forall b a. Ord b => (a -> b) -> [a] -> [a]
sortOn by [Char] -> a
strength [Char]
hand]
strength1 :: String -> [Int]
strength1 :: [Char] -> [Int]
strength1 [Char]
hand = [Char] -> Int
category [Char]
hand Int -> [Int] -> [Int]
forall a. a -> [a] -> [a]
: (Char -> Int) -> [Char] -> [Int]
forall a b. (a -> b) -> [a] -> [b]
map Char -> Int
val [Char]
hand
where
val :: Char -> Int
val Char
x = Maybe Int -> Int
forall a. HasCallStack => Maybe a -> a
fromJust (Char
x Char -> [Char] -> Maybe Int
forall a. Eq a => a -> [a] -> Maybe Int
`elemIndex` [Char]
"23456789TJQKA")
strength2 :: String -> [Int]
strength2 :: [Char] -> [Int]
strength2 [Char]
hand =
[Int] -> Int
forall a. Ord a => [a] -> a
forall (t :: * -> *) a. (Foldable t, Ord a) => t a -> a
maximum
[ [Char] -> Int
category ((Char -> Char) -> [Char] -> [Char]
forall a b. (a -> b) -> [a] -> [b]
map Char -> Char
rpl [Char]
hand)
| Char
alt <- [Char] -> [Char]
forall a. Eq a => [a] -> [a]
nub [Char]
hand
, let rpl :: Char -> Char
rpl Char
x = if Char
x Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
== Char
'J' then Char
alt else Char
x
] Int -> [Int] -> [Int]
forall a. a -> [a] -> [a]
: (Char -> Int) -> [Char] -> [Int]
forall a b. (a -> b) -> [a] -> [b]
map Char -> Int
val [Char]
hand
where
val :: Char -> Int
val Char
x = Maybe Int -> Int
forall a. HasCallStack => Maybe a -> a
fromJust (Char
x Char -> [Char] -> Maybe Int
forall a. Eq a => a -> [a] -> Maybe Int
`elemIndex` [Char]
"J23456789TQKA")
category :: String -> Int
category :: [Char] -> Int
category [Char]
hand =
case [Int] -> [Int]
forall a. Ord a => [a] -> [a]
sort (Map Char Int -> [Int]
forall a. Map Char a -> [a]
forall (t :: * -> *) a. Foldable t => t a -> [a]
toList ([Char] -> Map Char Int
forall (f :: * -> *) a. (Foldable f, Ord a) => f a -> Map a Int
counts [Char]
hand)) of
[Int
5] -> Int
6
[Int
1,Int
4] -> Int
5
[Int
2,Int
3] -> Int
4
[Int
1,Int
1,Int
3] -> Int
3
[Int
1,Int
2,Int
2] -> Int
2
[Int
1,Int
1,Int
1,Int
2] -> Int
1
[Int
1,Int
1,Int
1,Int
1,Int
1] -> Int
0
[Int]
_ -> [Char] -> Int
forall a. HasCallStack => [Char] -> a
error [Char]
"bad hand"