2021-12-04 12:52:39 +01:00
|
|
|
{-# LANGUAGE TupleSections #-}
|
2021-12-04 12:54:10 +01:00
|
|
|
import Data.List (transpose, partition)
|
2021-12-04 10:37:42 +01:00
|
|
|
|
|
|
|
main :: IO ()
|
|
|
|
main = readFile "4/input.txt" >>= print . solve . parse . lines
|
|
|
|
|
|
|
|
type Input = ([Int], [Board])
|
|
|
|
|
|
|
|
parse :: [String] -> Input
|
|
|
|
parse (l : ls) = (n, b)
|
2021-12-04 12:52:39 +01:00
|
|
|
where n = map read $ words [ if c == ',' then ' ' else c | c <- l ]
|
|
|
|
b = parseBoards (filter (/= "") ls)
|
2021-12-04 10:37:42 +01:00
|
|
|
|
|
|
|
parseBoards :: [String] -> [Board]
|
2021-12-04 12:52:39 +01:00
|
|
|
parseBoards [] = []
|
|
|
|
parseBoards l = parse a : parseBoards b
|
2021-12-04 13:09:47 +01:00
|
|
|
where (a,b) = splitAt 5 l
|
|
|
|
parse = map $ map ((,False) . read) . words
|
2021-12-04 10:37:42 +01:00
|
|
|
|
2021-12-04 12:52:39 +01:00
|
|
|
type Board = [[Cell]]
|
2021-12-04 10:37:42 +01:00
|
|
|
|
|
|
|
hasWon :: Board -> Bool
|
2021-12-04 13:09:47 +01:00
|
|
|
hasWon b = check b || check (transpose b)
|
2021-12-04 12:52:39 +01:00
|
|
|
where check = any $ all marked
|
2021-12-04 10:37:42 +01:00
|
|
|
|
2021-12-04 12:52:39 +01:00
|
|
|
score :: Int -> Board -> Int
|
2021-12-04 13:09:47 +01:00
|
|
|
score n b = n * sum [ x | c <- b, (x, False) <- c ]
|
2021-12-04 10:37:42 +01:00
|
|
|
|
2021-12-04 12:52:39 +01:00
|
|
|
call :: Int -> Board -> Board
|
|
|
|
call n = map (map mark)
|
2021-12-04 13:09:47 +01:00
|
|
|
where mark (x,s) = (x, s || x == n)
|
2021-12-04 10:37:42 +01:00
|
|
|
|
2021-12-04 13:09:47 +01:00
|
|
|
type Cell = (Int, Bool)
|
2021-12-04 10:37:42 +01:00
|
|
|
|
2021-12-04 12:52:39 +01:00
|
|
|
marked :: Cell -> Bool
|
2021-12-04 13:09:47 +01:00
|
|
|
marked = snd
|
2021-12-04 12:52:39 +01:00
|
|
|
|
|
|
|
solve :: Input -> (Int, Int)
|
2021-12-04 13:09:47 +01:00
|
|
|
solve (n, b) = (head r, last r)
|
|
|
|
where r = map (uncurry score) $ bingo n b
|
2021-12-04 10:37:42 +01:00
|
|
|
|
2021-12-04 12:52:39 +01:00
|
|
|
bingo :: [Int] -> [Board] -> [(Int, Board)]
|
|
|
|
bingo _ [] = []
|
|
|
|
bingo (n : ns) (b : bs) = map (n,) w ++ bingo ns l
|
|
|
|
where (w,l) = partition hasWon r
|
|
|
|
r = iter n (b : bs)
|
2021-12-04 10:37:42 +01:00
|
|
|
|
2021-12-04 12:52:39 +01:00
|
|
|
iter :: Int -> [Board] -> [Board]
|
|
|
|
iter _ [] = []
|
|
|
|
iter n (b : bs) = call n b : iter n bs
|