import Data.Maybe import Control.Monad import qualified Data.Map.Strict as Map import Data.Map.Strict ((!)) includeSelf :: Bool includeSelf = True getnames :: [String] -> Map.Map String Int getnames [] = Map.empty getnames (l:ls) = Map.insert (head (words l)) (Map.size n) n where n = getnames ls parse :: [String] -> Map.Map String Int -> Map.Map (Int,Int) Int parse [] names = Map.empty parse (l:ls) names = Map.insert (a,b) h $ parse ls names where w = words l an = head w bn = init $ last w a = names ! an b = names ! bn neg = w!!2 == "lose" hp = read $ w!!3 h = if neg then -hp else hp permutations :: [a] -> [[a]] permutations [] = [] permutations [v] = [[v]] permutations a = concat [map ((a!!i):) $ permutations $ take i a ++ drop (i + 1) a | i <- [0..(length a - 1)]] compute :: [Int] -> Map.Map (Int,Int) Int -> Int compute [] _ = 0 compute [_] _ = 0 compute l hm = fst $ foldl (\(acc,prev) i -> (acc + hm ! (prev,i) + hm ! (i,prev),i)) (0,last l) l addSelf :: Int -> Map.Map (Int,Int) Int -> Map.Map (Int,Int) Int addSelf n m = foldl (\mp i -> Map.insert (0,i) 0 $ Map.insert (i,0) 0 mp) m [1..n] day13 :: IO () day13 = do input <- liftM lines $ readFile "day13.txt" let names = getnames input let hapmap = if includeSelf then addSelf (length names) parsed else parsed where parsed = parse input names let perm = permutations [(if includeSelf then 0 else 1)..(length names)] print $ maximum [compute p hapmap | p <- perm] main = day13