Reputation: 29
the type is defined as follows: gap :: (Eq a) => a -> a -> [a] -> Maybe Int I have been stuck on this problem for more than an hour and have no idea how to approach the problem. I am aware that it requires the use of fold and am familiar with that topic. Please take into consideration that either foldl or foldr must be used. The output when called ought to look like this
gap 3 8 [1..10] =Just 5
gap 8 3 [1..10] =Nothing
gap 'h' 'l' "hello" =Just 2
gap 'h' 'z' "hello" =Nothing
Upvotes: 1
Views: 297
Reputation: 1
Maybe my solution isn't nice, but it works
import Control.Monad
import Data.Function
import Data.Foldable
(...) = (.) . (.)
gap x y = liftA2 ((guard . (> 0) =<<) ... liftA2 (subtract `on` fst))
(find ((==x) . snd)) (find((==y) . snd)) . zip [0..]
Upvotes: 0
Reputation: 1505
You might dropWhile
the list until you find the starting element and then fold from the right, starting with Nothing
, replacing that with Just 1
once you hit the end element, and fmap
ing +1
to the accumulator. In code:
gap :: Eq a => a -> a -> [a] -> Maybe Int
gap from to xs = case dropWhile (/= from) xs of
[] -> Nothing
(_:rest) -> gap' to rest
gap' :: Eq a => a -> [a] -> Maybe Int
gap' to = foldr f Nothing
where f x acc | x == to = Just 1
| otherwise = (+1) <$> acc
The nice thing is that it works correctly if you have several occurences of the elements in your sequence:
*Main> gap 3 8 $ [1..10] ++ [1..10]
Just 5
*Main> gap 3 8 [1, 2, 3, 3, 3, 8]
Just 3
Upvotes: 1