advent-2021/4/solution.hs

63 lines
1.5 KiB
Haskell
Raw Normal View History

2021-12-04 12:52:39 +01:00
{-# LANGUAGE TupleSections #-}
2021-12-04 10:37:42 +01:00
import Data.List
import Debug.Trace
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
where (a,b) = splitAt 5 l
parse = map $ map (Unmarked . 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
2021-12-04 12:52:39 +01:00
rows :: Board -> [[Cell]]
rows = id
cols :: Board -> [[Cell]]
cols = transpose
2021-12-04 10:37:42 +01:00
hasWon :: Board -> Bool
2021-12-04 12:52:39 +01:00
hasWon b = check (rows b) || check (cols b)
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
score n b = n * sum [ x | c <- b, Unmarked x <- 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)
where mark (Unmarked x) | x == n = Marked x
mark x = x
2021-12-04 10:37:42 +01:00
2021-12-04 12:52:39 +01:00
data Cell = Unmarked Int
| Marked Int
2021-12-04 10:37:42 +01:00
2021-12-04 12:52:39 +01:00
marked :: Cell -> Bool
marked (Marked _) = True
marked _ = False
solve :: Input -> (Int, Int)
solve input = (f input, g input)
where wins extr (n,b) = uncurry score $ extr $ bingo n b
f = wins head
g = wins last
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