module Main where import Debug.Trace (trace) import System.Environment (getArgs) main :: IO () main = do input <- readFile . head =<< getArgs print $ part1 input print $ part2 input part1 :: String -> Int part1 = length . filter (== 0) . scanl rotate 50 . map parse . lines rotate :: Integer -> Either Integer Integer -> Integer rotate pos (Left rot) = (pos - rot) `mod` 100 rotate pos (Right rot) = (pos + rot) `mod` 100 parse :: String -> Either Integer Integer parse ('L' : rest) = Left (read rest :: Integer) parse ('R' : rest) = Right (read rest :: Integer) parse s = error $ unwords [s, "is not on the form 'L$NUM' or 'R$NUM''"] test_input = "L68\nL30\nR48\nL5\nR60\nL55\nL1\nL99\nR14\nL82" part2 :: String -> Integer part2 = snd . head . reverse . scanl rotate2 (50, 0) . map parse . lines rotate2 :: (Integer, Integer) -> Either Integer Integer -> (Integer, Integer) rotate2 (pos, zeros) rot = let pos' = rotate pos rot newZeros = go pos rot in trace ("The dial is rotated " ++ show rot ++ " to point at " ++ show pos' ++ if newZeros > 0 then "; during this rotation it points to 0 " ++ (counting newZeros) else ".") (pos', zeros + newZeros) where counting :: Integer -> String counting 1 = "once" counting 2 = "twice" counting n = show n ++ " times" go :: Integer -> Either Integer Integer -> Integer go p (Left r) | p == r = 1 | r > 100 = 1 + go p (Left (r - 100)) | p /= 0 && p - r < 0 = 1 + go 0 (Left (r - p)) | otherwise = 0 go p (Right r) = (p + r) `div` 100 between :: Integer -> (Integer, Integer) -> Bool between x (mn, mx) = x < mx && x > mn