Search code examples
coding-stylepython

How to solve this Python puzzle in a much more elegant manner?


I was working through CoderByte 'Python' questions. Time is of essence, so the code may not be really readable but pretty straight forward. I will be interested in your approach. My code works for some words but testing with 'sentence' is giving me a different result, debugging as we speak. Please comment on my thinking!

Question :

Have the function LetterChanges(str) take the str parameter being passed and modify it using the following algorithm. Replace every letter in the string with the letter following it in the alphabet (ie. c becomes d, z becomes a). Then capitalize every vowel in this new string (a, e, i, o, u) and finally return this modified string. Use the Parameter Testing feature in the box below to test your code with different arguments. Do not modify the function name within the code. Do not put any code outside of the function and use the return keyword to return your answer from within the function.

My code :

def LetterChanges(str): 
    a = map(chr, range(97, 123))
    b = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z']
    b.remove('a')
    b.append('a')
    c = dict(zip(a,b))
    v = ['a', 'e', 'i', 'o', 'u']

    k = str
    for i in range(len(str)):
        if str[i] in a:
            k = k.replace(str[i], c[str[i]])

    l = k
    for i in range(len(k)):
        if k[i] in v:
            l = l.replace(k[i], k[i].upper())

    print l

# this call is needed to test your function
# keep this when you submit your code
LetterChanges(str)

Output :

zddzst -> AEEAUU {wrong}!
sentence -> UfOUfOdf {wrong}!

Solution

  • I would use str.translate() for this, it might look something like this:

    import string
    
    def LetterChanges(s):
        orig = string.letters
        new = string.ascii_lowercase[1:] + 'a' + string.ascii_uppercase[1:] + 'A'
        for vowel in 'aeiou':
            new = new.replace(vowel, vowel.upper())
    
        table = string.maketrans(orig, new)
        return s.translate(table)
    

    Example:

    >>> LetterChanges('sentence')
    'tfOUfOdf'
    

    For more efficiency, I would move the creation of table outside of the function so that it is only calculated once, instead of on each function call. Alternatively just hard code the end values for orig and new, like this:

    import string
    
    def LetterChanges(s):
        t = string.maketrans('abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ',
                             'bcdEfghIjklmnOpqrstUvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZA')
        return s.translate(t)
    

    edit: Here is a version that should work with coderbytes restrictions:

    def LetterChanges(s):
        orig = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
        new = 'bcdEfghIjklmnOpqrstUvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZA'
        result = ''
        for c in s:
            if c in orig:
                c = new[orig.index(c)]
            result += c
        return result