Ben313
Ben313

Reputation: 1668

How can I count vowel groups in a sentence using Haskell

I am trying to count vowel groups in a sentence.

My first attempt was to use list comprehension to reduce the sentence to a list of boolean values for each Char, depending on if it is a vowel or not. However, I'm not sure how to count the groups of consecutive "True" values in the list. Is there any trick to do this?

It was located in my textbook in a chapter dealing with lists and list comprehension, so I feel it has something to do with that.

Upvotes: 1

Views: 1745

Answers (3)

hammar
hammar

Reputation: 139930

Notice that you can count the vowel groups by looking at pairs of adjacent characters. Whenever you have a consonant followed by a vowel, you've found the start of a vowel group. The exception is when the string begins with a vowel, but that can be fixed by adding a dummy consonant to the front.

To look at adjacent pairs, you can use the common trick of zipping a list with its tail, so you can get the pairs like this:

> let xs = "upheaval"
> zip ('x':xs) xs
[('x','u'),('u','p'),('p','h'),('h','e'),('e','a'),('a','v'),('v','a'),('a','l')]

All you need to do now is count the number of pairs where the first letter is a consonant and the second is a vowel. You can for example do this using a list comprehension or filter, plus the length function.

Upvotes: 4

Ptival
Ptival

Reputation: 9447

Since I don't know whether it's a homework, I'm going to give you hints:

In Data.List:

group :: Eq a => [a] -> [[a]]
-- also interesting: groupBy :: (a -> a -> Bool) -> [a] -> [[a]]

-- for example:
-- group [True, True, False, False, False, True] =
-- [[True, True], [False, False, False], [True]]

You can write your own:

isVowel :: Char -> Bool

So you should be able to get the list you mention, with Bools, and now you want to count the groups that are "all True".

and :: [Bool] -> Bool
or :: [Bool] -> Bool

Any of these two fellows should prove useful, since both can reduce a list of all-equal boolean values into a single value equal to them. (EDIT: As mentioned in a comment, I'm overworking here, you just need to take the head of each "group". In fact, you can also guess the number of vowel groups just by looking at whether the first group is a vowel/consonant, and by counting the number of groups, since for sure there is an alternation vowel/consonant!)

And now, you just need to count the Trues in this final list, since each True represents a group of vowels!

filter :: (a -> Bool) -> [a] -> [a]
length :: [a] -> Int

You should be able to do the plumbing by yourself with these indications!

Upvotes: 5

Daniel Fischer
Daniel Fischer

Reputation: 183978

The Data.List module provides the handy groupBy function,

groupBy :: (a -> a -> Bool) -> [a] -> [[a]]

With that you can split the string into groups of consecutive vowels and non-vowels. There is no easy way using only list comprehensions, as far as I can see.

Upvotes: 2

Related Questions