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