Search code examples
pythonstringencryptioncaesar-cipher

Function rrot(rot, s) that takes as input an integer rot and a string s and returns a copy of s that s is reversed and then shifted by rot


I'm trying to implement a similar encoding scheme to that of the Caesar Cipher for strings that contain only capital letters, underscores, and periods. Rotations are to be performed using the alphabet order: ABCDEFGHIJKLMNOPQRSTUVWXYZ_.

Mycode so far:

def rrot(rot, s):
    'returns reverse rotation by rot of s'
    res = ''
    for c in s:
        x = ord(c)
        res += chr(x + rot)
        copy = res[::-1]
    return copy

Some examples of outputs are:

>>> rrot(1, 'ABCD')
'EDCB'
>>> rrot(3, 'YO_THERE.')
'CHUHKWBR.'
>>> rrot(1, '.DOT')
'UPEA'
>>> rrot(1, 'SNQZDRQDUDQ')
'REVERSE_ROT'

But when ran, it operates around the whole alphabet including symbols {[/ etc. I get the correct shifting for the moajority of the letters but get unwanted symbols. My incorrect outputs:

>>> rrot(3, 'YO_THERE.')
'1HUHKWbR\\'
>>> rrot(1, 'SNQZDRQDUDQ')
'REVERSE[ROT'

But this is correct:

>>> rrot(1, 'ABCD')
'EDCB'

How to i get it to follow the alphabetical order of just the charactes 'ABCDEFGHIJKLMNOPQRSTUVWXYZ_.'?


Solution

  • Your code can be simply fixed:

    def rrot(rot, s):
        'returns reverse rotation by rot of s'
        res = ''
        for c in s:
            x = ord(c)
            res += chr(x + rot)
            copy = res[::-1]
        return copy
    

    You can fix it to use another order for characters by replacing:

        x = ord(c)
        res += chr(x + rot)
    

    With say:

        x = alphabet.index(c)
        res += alphabet[(x + rot) % len(alphabet)]
    

    Consider:

    alphabet = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ_.'
    
    def rrot(rot, s):
        'returns reverse rotation by rot of s'
        res = ''
        for c in s:
            x = alphabet.index(c)
            res += alphabet[(x + rot) % len(alphabet)]
            copy = res[::-1]
        return copy
    

    Using those bad examples:

    >>> rrot(3, 'YO_THERE.')
    '1HUHKWbR\\'
    >>> rrot(1, 'SNQZDRQDUDQ')
    'REVERSE[ROT'
    

    Here the results of those examples:

    >>> rrot(3, 'YO_THERE.')
    'CHUHKWBR.'
    >>> rrot(1, 'SNQZDRQDUDQ')
    'REVERSE_ROT'
    

    Another way would be to build a translation table like:

    trans = dict(zip(alphabet, alphabet[rot:] + alphabet[:rot]))
    

    once outside the loop and then use:

        res += trans[c]
    

    Like this:

    alphabet = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ_.'
    
    def rrot(rot, s):
        'returns reverse rotation by rot of s'
        trans = dict(zip(alphabet, alphabet[rot:] + alphabet[:rot]))
        res = ''
        for c in s:
            res += trans[c]
            copy = res[::-1]
        return copy
    

    Which has the same results:

    >>> rrot(3, 'YO_THERE.')
    'CHUHKWBR.'
    >>> rrot(1, 'SNQZDRQDUDQ')
    'REVERSE_ROT'