python workout: exercise 5
pig latin
problem
Pig Latin (http://mng.bz/YrON) is a common children’s “secret” language in English- speaking countries. (It’s normally secret among children who forget that their parents were once children themselves.) The rules for translating words from English into Pig Latin are quite simple:
If the word begins with a vowel (a, e, i, o, or u), add “way” to the end of the word. So “air” becomes “airway” and “eat” becomes “eatway.”
If the word begins with any other letter, then we take the first letter, put it on the end of the word, and then add “ay.” Thus, “python” becomes “ythonpay” and “computer” becomes “omputercay.”
(And yes, I recognize that the rules can be made more sophisticated. Let’s keep it sim- ple for the purposes of this exercise.)
For this exercise, write a Python function (
pig_latin) that takes a string as input, assumed to be an English word. The function should return the translation of this word into Pig Latin. You may assume that the word contains no capital letters or punctuation.
attempts
This is a straightforward implementation problem – the logic has already been outlined:
def pig_latin(word: str) -> str:
vowels = {"a", "e", "i", "o", "u"}
if word[0] in vowels:
return word + "way"
else:
return word[1:] + word[0] + "ay"
print(pig_latin("air"))
print(pig_latin("computer"))
airway
omputercay
solution
A nice note: Python strings are sequences so our conditional can just be
if word[0] in 'aeiou'.
It’s technically not as efficient as a set. But with only 5 items, there’s no practical performance uplift with a set. And it’s cleaner.
The book’s solution:
def pig_latin(word):
if word[0] in 'aeiou':
return f'{word}way'
return f'{word[1:]}{word[0]}ay'
print(pig_latin('python'))
ythonpay
beyond the exercise
handle capitalised words
-
problem
If a word is capitalized (i.e., the first letter is capital- ized, but the rest of the word isn’t), then the Pig Latin translation should be similarly capitalized.
-
attempts
We just need to preserve the initial capital letter if present.
This begs the question: how should we test if the first letter is capitalised?
A couple approaches spring to mine:
- Use the ascii reprensetation of the first character and test whether it’s in the correct interval.
- Test whether the first character
word[0]is equal to itself butupper(i.e.word[0] == word[0].upper()) - Test whether the first character is in the set
string.ascii_uppercase.
There are probably other, cleaner ways. But let’s just use the second approach for now.
Let’s also take the solution’s implementation as the base to modify:
def pig_latin(word): if word[0] in 'aeiouAEIOU': return f'{word}way' if word[0] == word[0].upper(): return f'{word[1].upper()}{word[2:]}{word[0].lower()}ay' return f'{word[1:]}{word[0].lower()}ay' print(pig_latin("python")) print(pig_latin("air")) print(pig_latin("Air")) print(pig_latin("Python"))ythonpay airway Airway Ythonpay
handle punctuation
-
problem
If a word ends with punctuation, then that punctuation should be shifted to the end of the translated word.
-
attempts
If we assume ending punctuation are single characters only. We can just test if the last character is punctuation or not. And keep it aside until we return the modified word.
We can use
string.punctuation== to perform our test:import string def pig_latin(word): punctuation = "" if word[-1] in string.punctuation: punctuation = word[-1] word = word[:-1] if word[0] in 'aeiou': return f'{word}way{punctuation}' return f'{word[1:]}{word[0]}ay{punctuation}' print(pig_latin('python')) print(pig_latin('python.'))ythonpay ythonpay.
consider an alternative versio of pig latin
-
problem
We don’t check to see if the first letter is a vowel, but, rather, we check to see if the word contains two different vowels. If it does, we don’t move the first letter to the end. Because the word “wine” contains two different vowels (“i” and “e”), we’ll add “way” to the end of it, giv- ing us “wineway.” By contrast, the word “wind” contains only one vowel, so we would move the first letter to the end and add “ay,” rendering it “indway.” How would you check for two different vowels in the word?
-
attempts
The question gives the hint to use sets and even asks the question for us: how can we check a word has 2 different vowels?
The set hint would suggest iterating through a word and adding each letter to a set of vowels. If the length of the resultant set is greater than 1, we know the input word to contain at least 2 different vowels.
We should be able to use a comprehension to do this:
def pig_latin(word): word_vowels = {l for l in word if l in 'aeiou'} if len(word_vowels) > 1: return f'{word}way' return f'{word[1:]}{word[0]}ay' print(pig_latin('wine')) print(pig_latin('wind'))wineway indway