Strict fold
[advent-of-code-16.git] / advent15.hs
1 import Text.Parsec
2 import Text.ParserCombinators.Parsec.Number
3
4 type Disk = (Int -> Bool)
5
6 main :: IO ()
7 main = do
8 text <- readFile "advent15.txt"
9 let disks = successfulParse $ parseIfile text
10 part1 disks
11 part2 disks
12
13 part1 :: [Disk] -> IO ()
14 part1 disks = print $ head $ filter (canFall disks) [0..]
15
16 part2 :: [Disk] -> IO ()
17 part2 disks = print $ head $ filter (canFall disks2) [0..]
18 where disks2 = disks ++ [diskify 7 11 0]
19
20 canFall :: [Disk] -> Int -> Bool
21 canFall ds i = all (\d -> (d i)) ds
22
23
24 instructionFile = instructionLine `endBy` newline
25 instructionLine = diskify <$> (string "Disc #" *> int)
26 <*> (string " has " *> int)
27 <*> (string " positions; at time=0, it is at position " *> int)
28 <* (string ".")
29
30 diskify :: Int -> Int -> Int -> (Int -> Bool)
31 diskify n size pos0 = (\i -> (size + n + pos0 + i) `mod` size == 0)
32
33 parseIfile :: String -> Either ParseError [Disk]
34 parseIfile input = parse instructionFile "(unknown)" input
35
36 parseIline :: String -> Either ParseError Disk
37 parseIline input = parse instructionLine "(unknown)" input
38
39 successfulParse :: Either ParseError [a] -> [a]
40 successfulParse (Left _) = []
41 successfulParse (Right a) = a