Python program to translate sentences from “bird language”

Given a sentence in 'bird language', where there are two rules:

1. After each consonant there is a random vowel added. For example if the consonant is "l" it will end as "la" or "le"...
2. After each vowel there are two extra vowels which are the same as the first. For example if there is a "u" it will end as "uuu"

• Vowels are "aeiouy"

Examples:

• hieeelalaooohello
• hoooowe yyyooouuu duoooiiinehow you doin
• aaa bo cy da eee fea b c d e f
• sooooso aaaaaaaaasos aaa

The code is:

VOWELS = "aeiouy"

def translate(phrase):

result = ""
num_of_letters_to_ignore = 0

for i, letter in enumerate(phrase):
if num_of_letters_to_ignore > 0:
num_of_letters_to_ignore -= 1
continue

if letter in VOWELS:
num_of_letters_to_ignore += 2
elif letter.isalpha():
num_of_letters_to_ignore += 1
result += letter

return result


How can it be improved?

EDIT: I have added the first sentence which was missing where it is correctly specified that y is in the vowels!

• @jonrsharpe Seems to work now with the inclusion of the global constant. – Graipher May 25 '19 at 21:40

Considering that you have four concrete test cases, it would be a good idea to put them in a docstring as doctests.

Your iteration is awkward. First of all, you never use i, so there is no need to call enumerate(). A better way to conditionally skip ahead is to call next() on an iterator over the phrase.

def translate(phrase):
"""
Translate the phrase from bird language.

>>> translate('hieeelalaooo')
'hello'
>>> translate('hoooowe yyyooouuu duoooiiine')
'how you doin'
>>> translate('aaa bo cy da eee fe')
'a b c d e f'
>>> translate('sooooso aaaaaaaaa')
'sos aaa'
"""
phrase = iter(phrase)
result = ""
for letter in phrase:
result += letter
if letter in VOWELS:   # Vowel. Skip the next two characters.
next(phrase)
next(phrase)
elif letter.isalpha(): # Consonant. Skip the next character.
next(phrase)
return result


A much more compact solution, though, would be to perform a regular expression substitution.

import re

def translate(phrase):
return re.sub(r'([aeiouy])\1\1|([a-z])[aeiouy]', r'\1\2', phrase, flags=re.I)


At first I thought it can be improved in more functional way, but after several minutes I see your solution is pretty optimal and elegant. I see two places for improvement:

• for i, letter in enumerate(phrase): - you don't use i so you don't need enumerate. You can replace it with an ordinary loop: for letter in phrase:

• You can add try-except block or check that phrase is actually a string, not a random type object

• Hello, @vurmmux could you explain me how could we do the try and catch which you suggest, please? – enoy May 24 '19 at 22:04
• Type verification is not common practice in Python. – 200_success May 25 '19 at 1:20