module Main where import Data.List.Split (chunksOf, splitOn) import Debug.Trace (traceShowId) import Data.List (transpose) main :: IO () main = interact solution type Board = [(Bool, Int)] second :: (b -> c) -> (a, b) -> (a, c) second f (a, b) = (a, f b) second2 :: (a -> b -> c) -> (a, b) -> (a, c) second2 f (a, b) = (a, f a b) first :: (a -> c) -> (a, b) -> (c, b) first f (a, b) = (f a, b) solution :: String -> String solution = show . second2 applydraws . second ( chunksOf 25 . zip (repeat False) . map (read :: String -> Int) . concatMap words ) . first ( map (read :: String -> Int) . splitOn "," ) . (\x -> (head x, tail x)) . lines select :: Int -> Board -> Board select n = map (\(d, p) -> ((n == p) || d, p)) hasWon :: Board -> Bool hasWon b = any and r || any and (transpose r) where r = chunksOf 5 (map fst b) score :: Int -> Board -> Int score lastn b = lastn * boardleft b where boardleft = sum . map snd . filter (not . fst) applydraw :: Int -> [Board] -> [Board] applydraw n = map (select n) applydraws ::[Int] -> [Board] -> [(Int, [Board])] applydraws [] _ = [] applydraws (n:ns) b = (n, nb) : applydraws ns nb where nb = applydraw n b getWinning :: [[Board]] -- ^ Mapped boards -> Board getWinning [] = error "WTF" getWinning (bs:r) = if any hasWon bs then getWinning' bs else getWinning r where getWinning' :: [Board] -> Board getWinning' (b:bs) | hasWon b = b | otherwise = getWinning' bs getWinning' [] = error "Wtf"