42 lines
1.4 KiB
Haskell
42 lines
1.4 KiB
Haskell
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 |