Parse the input:
parse :: String -> [Int]
parse = map f . lines
where f ('L':r) = negate (read r)
f ('R':r) = read rRotate the dial starting at 50, and count the number of times
we stop at zero on the way. Of note is that the dial cycles back
to zero after 100, so our check mustn’t just be == 0
but rather, mod n 100 == 0:
count :: (a -> Bool) -> [a] -> Int
count pred = length . filter pred
clicks :: [Int] -> Int
clicks = count ((== 0) . (`mod` 100)) . scanl (+) 50Thus, the solution to the first part is given by:
p1 :: [Int] -> Int
p1 = clicksThis part is ever so slightly different, instead of the number of times we stop are zero, we are required to additionally calculate the number of times we pass through zero.
To think of this a bit differently, the first part has lower
degree of precision: we only perform the check after the dial is
fully rotated. The second part requires us to perform the check
with higher degree of precision: after each movement by 1. Thus,
if we modify our list to change one rotation of size N into N
rotations of size 1, we will be able to reuse our
clicks method:
transform :: Int -> [Int]
transform n = replicate (abs n) (signum n)
p2 :: [Int] -> Int
p2 = clicks . concatMap transformFinally, a main function to wrap it all up:
main = do
n <- parse <$> getContents
print $ p1 n
print $ p2 n