data Reindeer = Reindeer {speed :: Int, speedduration :: Int, resttime :: Int} deriving (Show) data Status = Status {spedfor :: Int, restedfor :: Int, travelled :: Int, points :: Int} deriving (Show) parse :: String -> Reindeer parse l = Reindeer s d r where w = words l s = read $ w !! 3 d = read $ w !! 6 r = read $ w !! 13 simulate :: Int -> [Reindeer] -> [Status] simulate 0 r = replicate (length r) $ Status 0 0 0 0 simulate n r = updatepoints $ map update $ zip r $ simulate (n-1) r where update (rein,stat) = if spe > 0 && spe < spemax then Status (spe+1) 0 (dis+speed rein) pts else if spe == spemax then Status 0 1 dis pts else if res > 0 && res < resmax then Status 0 (res+1) dis pts else Status 1 res (dis+speed rein) pts where spe = spedfor stat res = restedfor stat dis = travelled stat pts = points stat spemax = speedduration rein resmax = resttime rein updatepoints stats = [if travelled s == maxtrav then Status (spedfor s) (restedfor s) (travelled s) (points s + 1) else s | s <- stats] where maxtrav = maximum $ map travelled stats day14 :: IO () day14 = do input <- readFile "day14.txt" let inputl = lines input let rein = map parse inputl let result = simulate 2503 rein print $ maximum $ map points result -- part 1: map travelled; part 2: map points main = day14