Strict fold
[advent-of-code-16.git] / advent18f.hs
1 import Data.List (tails, foldl')
2
3 -- input = "..^^."
4 -- input = ".^^.^.^^^^"
5 input = "^.^^^.^..^....^^....^^^^.^^.^...^^.^.^^.^^.^^..^.^...^.^..^.^^.^..^.....^^^.^.^^^..^^...^^^...^...^."
6
7 main :: IO ()
8 main = do
9 part1
10 part2
11
12 part1 :: IO ()
13 part1 = print $ fst $ foldl' nextRowFold (countSafe row, row) [2..40]
14 where row = readRow input
15
16 part2 :: IO ()
17 part2 = print $ fst $ foldl' nextRowFold (countSafe row, row) [2..400000]
18 where row = readRow input
19
20 readRow :: String -> [Bool]
21 readRow = map (=='^')
22
23 showRow :: [Bool] -> String
24 showRow = map (\c -> if c then '^' else '.')
25
26 extended :: [Bool] -> [Bool]
27 extended row = [False] ++ row ++ [False]
28
29 nextRow :: [Bool] -> [Bool]
30 nextRow = map (isTrap) . segments . extended
31
32 nextRowFold :: (Int, [Bool]) -> Int -> (Int, [Bool])
33 nextRowFold (n, row) _ = (n + countSafe newRow, newRow)
34 where newRow = nextRow row
35
36 countSafe :: [Bool] -> Int
37 countSafe = length . filter (not)
38
39 segments :: [a] -> [[a]]
40 segments = filter ((==3) . length) . map (take 3) . tails
41
42 isTrap :: [Bool] -> Bool
43 isTrap segment
44 | segment == [True, True, False] = True
45 | segment == [False, True, True] = True
46 | segment == [True, False, False] = True
47 | segment == [False, False, True] = True
48 | otherwise = False