2
\$\begingroup\$

I wrote this function to count the syllables in a word using Python to complete an exercise.

The exercise's text is:

Return the number of syllables in the given word, according to this rule: Each contiguous sequence of one or more vowels is a syllable, with the following exception: a lone "e" at the end of a word is not considered a syllable unless the word has no other syllables. You should consider y a vowel.

I also disagree with the text because using the given instructions the syllable count for the word "example" are 2 and should be 3.

But, as discussed in the comments, the exercise text is the one that I implemented and would like to get suggestions and improvements for.

def count_syllables(word):
    word = word.lower()
    counter = 0
    is_previous_vowel = False
    for index, value in enumerate(word):
        if value in ["a", "e", "i", "o", "u", "y"]:
            if index == len(word) - 1:
                if value == "e":
                    if counter == 0:
                        counter += 1
                else:
                    counter += 1
            else:
                if is_previous_vowel == True:
                    counter += 1
                    is_previous_vowel = False
                    break
            is_previous_vowel = True
        else:
            if is_previous_vowel == True:
                counter += 1
            is_previous_vowel = False
    print ("In \"{}\" I count {} syllables".format(word, counter))

count_syllables("coding")
\$\endgroup\$
  • \$\begingroup\$ You could possibly try bit masking. Using ord function you can convert any character to its 8 bit integer representation. Then you could write instead of for an while loop till end character is found (0x00), where your counter would then be counter += 1 if (ord(word[i]) & 97 == 97 else 0. You can see what integer representations of your vowel letters are by going into console and just list(map(ord, 'aeiouy')). With while loop you can save in speed by not assigning length of string. GKeyWords: Bitwise operators. \$\endgroup\$ – Danilo Jul 14 at 21:45
  • 1
    \$\begingroup\$ I also disagree with the text, although for the different reasons. There are plenty of words in which successive vowels form distinct syllables; there are plenty of (mostly borrowed) words in which final e forms a syllable; treatment of y is too simplistic (say, beyond). However I am curious how did you come up with 4 syllables in example. Nevertheless, the problem statement is what has to be implemented. \$\endgroup\$ – vnp Jul 14 at 22:02
  • \$\begingroup\$ @vnp Horrible typo! 3 and not 4 syllables for example, obviously. I also see that the exercise track was written in this way for simplification. Indeed the Code Review should be mainly code related so I will consider as good answer the one that improves my code and just follow the given exercise track. Obviously if a great coder comes with a complete solution working for real English that would simply be awesome for me and other people on the planet, I guess :) \$\endgroup\$ – Pitto Jul 14 at 22:18
  • \$\begingroup\$ So you just want someone to do the example instead of you ? Smart. You are missing the main question. The code works so you have no major bugs. There is of course optimisation and readability/speed improvement, but since you've changed your question a bunch of times ( i don't mind that ), it is unclear what are you expecting to get from Review. \$\endgroup\$ – Danilo Jul 14 at 22:23
  • 1
    \$\begingroup\$ @Danilo What do you mean by "instead of me"? I already did a complete and working version of the code, as you can read in the post. All I am looking for is improvements / more efficient / more elegant version of it. This is the main idea behind this site, no? On the other side, while discussing with vpn, seemed obvious that also the text of the exercise would not obtain 100% correctness in English. I just think it would be nice bonus if we can get a 100% working version in English but it is not the aim of this question, only focused on given code improvements. \$\endgroup\$ – Pitto Jul 14 at 22:28
4
\$\begingroup\$

As a good practice to promote code reuse, the function should return a numeric result. The print() should be done by the caller.

Constantly referring to is_previous_vowel is tedious. There are a couple of solutions you could use involving itertools. In particular, groupby() and zip_longest() could be useful.

Ultimately, the simplest solution is to use a regular expression to declare what you are looking for: one or more consecutive vowels ('[aeiouy]+'), but not an e at the end ('(?!e$)).

import re

def count_syllables(word):
    return len(
        re.findall('(?!e$)[aeiouy]+', word, re.I) +
        re.findall('^[^aeiouy]*e$', word, re.I)
    )
\$\endgroup\$
  • 1
    \$\begingroup\$ Fails (i.e. returns 0) when the terminating e is the only vowel in the word. \$\endgroup\$ – vnp Jul 14 at 23:38
  • \$\begingroup\$ @vnp I missed that requirement. Added special case in Rev 2. \$\endgroup\$ – 200_success Jul 15 at 0:45
  • \$\begingroup\$ This is a masterpiece \$\endgroup\$ – Pitto Jul 15 at 7:50

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.