1

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.

3
  • Just to be sure: is this the Table type you are using? Commented Feb 7, 2017 at 17:23
  • I remember Table from a previous homework problem posted. I think it's just an association list, maybe a previous homework assignment to implement it. Commented Feb 7, 2017 at 18:50
  • newtype Table a b = T [(a,b)] Commented Feb 7, 2017 at 23:22

3 Answers 3

1

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.

Sign up to request clarification or add additional context in comments.

Comments

1

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.

Comments

1

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...

1 Comment

Bingo! I was thinking of recursion backwardsly!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.