Search code examples
pythonfunctionasciiuser-defined-functionsletters-and-numbers

Error in replacing alphabets with the next one using ascii_letters


The problem is a known one: Given a sentence, return the sentence with all its letters transposed by 1 in the alphabet, but only if the letter is a-y.

I understand similar questions have been asked here bunch of times, but the solution I applied in my case actually came from one of these stackoverflow answers and the function still keeps jumping 2-3 letters ahead:

from string import ascii_letters

def inverter(sentence):
    for x in sentence:
        if x in ascii_letters and x!= 'z' and x != ' ':
            sentence = sentence.replace(x,ascii_letters[ascii_letters.index(x)+1])
        else:
            sentence = sentence
    return sentence

sent3 = 'a quick brown fox jumps over the lazy dog'

inverter(sent3)

Output:

'c uwkem cuqzq hqz kwnqu qwfu uif mczz eqh'

What could be going wrong in the loop of mutation?


Solution

  • Use ord to convert each of the certain characters into its number form, add 1, and use chr to convert the integer back to a character:

    from string import ascii_letters
    
    def inverter(sentence):
        a_to_y = ascii_letters[:25]
        s = ''
        for i in sentence:
            if i in a_to_y:
                i = chr(ord(i) + 1)
            s += i
        return s
    
    sent3 = 'a quick brown fox jumps over the lazy dog'
    
    print(inverter(sent3))
    

    Output:

    b rvjdl cspxo gpy kvnqt pwfs uif mbzz eph
    

    Here's a one-liner:

    def inverter(sentence):
        return ''.join([chr(ord(i) + 1) if i in 'abcdefghijklmnopqrstuvwxy' else i for i in sentence])
    
    sent3 = 'a quick brown fox jumps over the lazy dog'
    
    print(inverter(sent3))
    

    Here is why your for loop didn't work:

    The str.replace method replaces all occurrences of the specified string with the other specified string, not just one.

    Let's say your sentence is "apple anna".

    With for x in sentence:, the first letter will be "a".

    Since "a" meets the condition if x in ascii_letters and x!= 'z' and x != ' ':, the "a" will be replaced with "b", but not just that "a", also all the other "a"s in that string

    By the time the iteration reaches the next "a", the "a" will already be a "b", so the former "a" will be replaced with a "c", and then the next former will be "c" to "d"!

    The same applies for your string, with most of the letters in it.