-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathrun.hs
45 lines (34 loc) · 1.06 KB
/
run.hs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
import Data.Void (Void)
import Text.Megaparsec
import Text.Megaparsec.Char
unsafeRight :: Show a => Either a b -> b
unsafeRight (Right x) = x
unsafeRight (Left x) = error $ show x
type Parser = Parsec Void String
num :: Parser Int
num = read <$> some digitChar
layerP :: Parser (Int, Int)
layerP = (,) <$> num <*> (string ": " *> num)
parseAll :: String -> [(Int, Int)]
parseAll = map unsafeRight
. map (parse layerP "")
. filter (not . null)
. lines
caughtInLayer :: Int -> Int -> Int -> Bool
caughtInLayer s l d = (s + l) `mod` (2 * (d - 1)) == 0
tripWeight :: Int -> [(Int, Int)] -> Int
tripWeight startAt = sum . map weight
where weight (i, d)
| caughtInLayer startAt i d = i * d
| otherwise = 0
caught :: Int -> [(Int, Int)] -> Bool
caught startAt = any (uncurry (caughtInLayer startAt))
part1 :: [(Int, Int)] -> Int
part1 = tripWeight 0
part2 :: [(Int, Int)] -> Int
part2 input = head $ filter (not . flip caught input) $ [0..]
main :: IO ()
main = do
input <- parseAll <$> readFile "input.txt"
print (part1 input)
print (part2 input)