Reputation: 105
I'm new to haskell and I got stuck in a little program I tried to make. I want to count number of times my guard statement goes through in all recursion rounds and then return that as Int. For example if c1
is 'a'
, c2
is 'b'
, g
is 2
and s
is "aaabbb"
then returned int would be 2, because my guard statement is true in 2 cases.
I tried to make variable x
and then add x + 1
to it every time guard statement happens. That didn't work because I learnt that in Haskell variable you set is always static so for example setting x = 0
at start would set that x
to 0 every recursion round.
Here's my code:
gaps :: (Char, Char) -> Int -> String -> Int
gaps (c1,c2) g (s:xs)
| c1 == s && c2 == (s:xs) !! g = --Count how many times this statement happens --
| otherwise = gaps (c1,c2) g xs
Upvotes: 2
Views: 157
Reputation: 275
Off the back of questions on how to make this thing safer, I have made the following code snippet, borrowing from Ismor's answer.
-- a way to safely get the nth item from a list
get' :: [a] -> Int -> Maybe a
get' [] _ = Nothing
get' (x:xs) 0 = Just x
get' (x:xs) n
| n > 0 = get' xs (n-1)
| otherwise = Nothing
-- takes a Maybe value. if it's Nothing, return 0. if it's Just a value, compare
-- the value and a given param, if equal return 1, else 0
seeEqual:: (Num b, Eq a) => Maybe a -> a -> b
seeEqual Nothing _ = 0
seeEqual (Just a) b
| a==b = 1
| otherwise = 0
-- I have edited the first guard so that it checks c1 and s, then tries to calculate
-- whether c2 and the specific list item are equal, and then recurses as before
gaps :: (Char, Char) -> Int -> String -> Int
gaps _ _ [] = 0 -- base case
gaps (c1,c2) g (s:xs)
| c1 == s = (seeEqual (get' (s:xs) g) c2) + gaps (c1,c2) g xs -- add one to final result
| otherwise = gaps (c1,c2) g xs
I do not claim that this is perfect, but I do think this is safe and shouldn't throw any exceptions or raise any errors.
Prelude> gaps ('a','b') 3 "aaaababbb"
3
Prelude> gaps ('a','b') 3 "aaaabbabb"
2
Upvotes: 1
Reputation: 5063
Just add 1
and call the function recursively
gaps :: (Char, Char) -> Int -> String -> Int
gaps _ _ [] = 0 -- base case
gaps (c1,c2) g (s:xs)
| c1 == s && c2 == (s:xs) !! g = 1 + gaps (c1,c2) g xs -- add one to final result
| otherwise = gaps (c1,c2) g xs
> gaps ('a','b') 2 "aaabbb"
2
> gaps ('a','b') 3 "aaaabbbb"
3
Be carefull when using !!
. It isn't total and might fail if your input string has c1
's values less than g
positions before the end of the string
> gaps ('a','b') 3 "aaaababbb" -- doesn't fail
3
> gaps ('a','b') 3 "aaaabbabb" -- does fail!!!!
Upvotes: 5