Reputation: 33
I am trying to count the number of characters in a string coupled with a recursive function but it does not seem to be working.
{- characterCounts s
PRE: True
POST: a table that maps each character that occurs in s to the number of
times the character occurs in s
EXAMPLES:
-}
characterCounts :: String -> Table Char Int
characterCounts [] = Table.empty
characterCounts s = characterCountsAux s Table.empty
characterCountsAux:: String -> Table Char Int -> Table Char Int
characterCountsAux [] table = table
characterCountsAux (x:xs) table = characterCountsAux xs (Table.insert (table) x (count x (x:xs) ))
count:: Char -> String -> Int
count c s = length $ filter (==c) s
so in case I do: characterCounts "atraa"
I should get T [('a',3),('t',1),('r',1)]
but instead I get T [('a',1),('t',1),('r',1)]
.
Suggestions will be appreciated.
Upvotes: 1
Views: 694
Reputation: 201
When you call characterCountsAux xs _ you are giving your function the remainder of the list. That means that on the 4th iteration you are calling
characterCountsAux "aa" T [('a',3),('t',1),('r',1)]
which changes the table to T [('a',2),('t',1),('r',1)] and on the next iteration we have
characterCountsAux "a" T [('a',2),('t',1),('r',1)]
which gives you the final T[('a',1),('t',1),('r',1)].
A naive solution would be removing all occurrences of x from xs i.e.
characterCountsAux (x:xs) table = characterCountsAux (filter (/= x) xs) (Table.insert (table) x (count x (x:xs) ))
Of course it doesn't look very efficient...
Upvotes: 1
Reputation: 191
Your Table looks a lot like a Map. So, if you can use Maps you could try the following:
import qualified Data.Map as M
characterCounts :: [Char] -> M.Map Char Int
characterCounts = foldr ((flip $ M.insertWith (+)) 1) M.empty
Now, characterCounts "atraa"
returns fromList [('a',3),('r',1),('t',1)]
, i.e. a Map Char Int
similar to the Table Char Int
you are asking for. It should be easy to implement a conversion, if needed.
Upvotes: 1
Reputation: 1394
I don't seem to have a "Table" module (in GHC).
Your code looks odd: you seem to loop over the all the chars and then try to loop again when counting (but only over the tail of the list).
There is a "count" function in the Table module linked in the other comment.
You should probably do something like
Table.insert table x ((count table x) + 1)
and remove your "count" function.
Addition: you also need to handle the first occurrence of a char in the table.
Upvotes: 1