module Day04 where import Data.List.Split ( splitOn ) import Data.Maybe (catMaybes, mapMaybe, listToMaybe) import Data.List (transpose, sort) type Board = [[Int]] checkRowTime :: [Int] -> [Int] -> Maybe Int checkRowTime values row = fmap maximum elemTimes where elemTimes = mapM (`lookup` times) row times = zip values [0..] checkBingoTime :: [Int] -> Board -> Maybe Int checkBingoTime values board = listToMaybe $ sort $ catMaybes $ horTimes ++ verTimes where horTimes = map (checkRowTime values) board verTimes = map (checkRowTime values) (transpose board) calculateScore :: [Int] -> Int -> Board -> Int calculateScore values time card = values!!time * sum unmarked where marked = take (time+1) values unmarked = filter (`notElem` marked) $ concat card main :: IO () main = do firstLine <- getLine let values = map (read :: String->Int) $ splitOn "," firstLine _ <- getLine input <- getContents let cards = map (map (map (read::String->Int))) $ map (map words) $ splitOn [""] $ lines input let cardsWithTime = mapMaybe (\card -> fmap (\t -> (t,card)) (checkBingoTime values card)) cards putStr "part 1: " let (time,card) = minimum cardsWithTime print $ calculateScore values time card putStr "part 2: " let (time,card) = maximum cardsWithTime print $ calculateScore values time card