diff options
| author | Jan Tuomi <jans.tuomi@gmail.com> | 2021-12-07 12:43:51 +0200 |
|---|---|---|
| committer | Jan Tuomi <jans.tuomi@gmail.com> | 2021-12-07 14:18:09 +0200 |
| commit | 3142bbcc613f880a9356ac1c837e2902f12a168e (patch) | |
| tree | 45859d8b08c09a1b90eb986ff8f388eb32d1693d /day04/main.hs | |
| parent | 38e975a00a4b4739bf3b818fd8632578660fa05b (diff) | |
Day 04
Diffstat (limited to 'day04/main.hs')
| -rw-r--r-- | day04/main.hs | 59 |
1 files changed, 59 insertions, 0 deletions
diff --git a/day04/main.hs b/day04/main.hs new file mode 100644 index 0000000..1904c88 --- /dev/null +++ b/day04/main.hs @@ -0,0 +1,59 @@ +module Main where + +import Data.Foldable (find) +import Data.Maybe (fromJust, isJust) +import Debug.Trace (trace, traceShow) +import Utils + +type Board = [[Int]] + +toGroupsOfN :: Int -> [a] -> [[a]] +toGroupsOfN n [] = [] +toGroupsOfN n lst = take n lst : toGroupsOfN n (drop n lst) + +rowBingo :: [Int] -> Board -> Bool +rowBingo draws = any (all (`elem` draws)) + +findBingo :: [Int] -> Board -> Maybe Int +findBingo draws board = + let horizFound = rowBingo draws board + vertFound = rowBingo draws (transpose board) + in if horizFound || vertFound + then Just $ sumUnmarked draws board + else Nothing + +sumUnmarked :: [Int] -> Board -> Int +sumUnmarked draws board = + let sumRowUnmarked row = filter (`notElem` draws) row $> sum + in board $> map sumRowUnmarked .> sum + +recur :: [Int] -> Int -> [Board] -> () +recur draws n boards + | n > length draws = () + | otherwise = + let drawn = take n draws + notDrawn = drop n draws + bingoResults = boards $> mapWithIndex (findBingo drawn) .> filter (\(_, m) -> isJust m) + winningBoards = map (\(i, m) -> (i, last drawn * fromJust m)) bingoResults + nWinning = length winningBoards + indicesToRemove = map fst winningBoards + winningScores = map snd winningBoards + restBoards = removeAt indicesToRemove boards + in trace ("Found " ++ show nWinning ++ " results at " ++ show n ++ ": " ++ show winningScores ++ ", boards left: " ++ show (length restBoards)) $ + recur draws (n + 1) restBoards + +run :: [Int] -> [Board] -> () +run draws = recur draws 1 + +main :: IO () +main = + do + contents <- getContents + let input = + contents + $> lines + .> filter (not . null) + + let draws = head input $> splitOn (== ',') .> map read :: [Int] + let boards = tail input $> map (words .> map read) .> toGroupsOfN 5 :: [Board] + run draws boards $> print |
