This encoding function expects the following output,
code "aaccbbaa" = [('a',2),('c',2),('b',2),('a',2)
However, this is my output.
code "aaccbbaa" = [('a',4),('c',2),('b',2)]
Here is my function,
code :: Eq a => [a] -> [(a,Int)]
code [] = []
code (x:xs) = [(x, length(filter(==x)(x:xs)))] ++ code(filter (/=x)(xs))
How do I make it recount that when the next alpha letter appears?
There is a group function in Data.List
code :: Eq a => [a] -> [(a,Int)]
code = map (\x -> (head x, length x)) . group
λ> code "aaccbbaa"
[('a',2),('c',2),('b',2),('a',2)]
A foldr with a helper function should be sufficient to handle this job as follows;
code :: Char -> [(Char,Int)] -> [(Char,Int)]
code c [(_,0)] = [(c,1)]
code c ((x,n):ts) | c == x = (x,n+1):ts
| otherwise = (c,1):(x,n):ts
rle :: String -> [(Char,Int)]
rle = foldr code [(' ',0)]
Well as per your comment to accept any type with instances of Eq Class we may simplify the rle function. On the other hand the accepted answer involves 3 time taking operations like group, map and length. For a single use it won't matter, however if you will be using this function millions of times on some words or sentences then i would advise the following which only runs once through the list.
rle :: Eq a => [a] -> [(a,Int)]
rle = foldr code []
where code c [] = [(c,1)]
code c ((x,n):ts) | c == x = (x,n+1):ts
| otherwise = (c,1):(x,n):ts
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With