Search code examples
pythonstringencryptionrot13

Python text encryption: rot13


I am currently doing an assignment that encrypts text by using rot 13, but some of my text wont register.

# cgi is to escape html
# import cgi

def rot13(s):
    #string encrypted
    scrypt=''
    alph='abcdefghijklmonpqrstuvwxyz'
    for c in s:
        # check if char is in alphabet
        if c.lower() in alph:
            #find c in alph and return its place
            i = alph.find(c.lower())

            #encrypt char = c incremented by 13
            ccrypt = alph[ i+13 : i+14 ]

            #add encrypted char to string
            if c==c.lower():
                scrypt+=ccrypt
            if c==c.upper():
                scrypt+=ccrypt.upper()

        #dont encrypt special chars or spaces
        else:
            scrypt+=c

    return scrypt
    # return cgi.escape(scrypt, quote = True)


given_string = 'Rot13 Test'
print rot13(given_string) 

OUTPUT:

13 r
[Finished in 0.0s]

Solution

  • First thing that may have caused you some problems - your string list has the n and the o switched, so you'll want to adjust that :) As for the algorithm, when you run:

    ccrypt = alph[ i+13 : i+14 ]
    

    Think of what happens when you get 25 back from the first iteration (for z). You are now looking for the index position alph[38:39] (side note: you can actually just say alph[38]), which is far past the bounds of the 26-character string, which will return '':

    In [1]: s = 'abcde'
    
    In [2]: s[2]
    Out[2]: 'c'
    
    In [3]: s[2:3]
    Out[3]: 'c'
    
    In [4]: s[49:50]
    Out[4]: ''
    

    As for how to fix it, there are a number of interesting methods. Your code functions just fine with a few modifications. One thing you could do is create a mapping of characters that are already 'rotated' 13 positions:

    alph = 'abcdefghijklmnopqrstuvwxyz'
    coded = 'nopqrstuvwxyzabcdefghijklm'
    

    All we did here is split the original list into halves of 13 and then swap them - we now know that if we take a letter like a and get its position (0), the same position in the coded list will be the rot13 value. As this is for an assignment I won't spell out how to do it, but see if that gets you on the right track (and @Makoto's suggestion is a perfect way to check your results).