One line Caesar

Updated TrustyTony 0 Tallied Votes 416 Views Share

I was not happy of solution http://chaos.weblogs.us/archives/331 for one line Ceasar cipher, so I wrote my own version without import by using raw_input (change to input for Python3). Chance to play little with memoryview object also.

Crypt: give displacement amount for shift
Decrypt: give -displacement amount shift

print ''.join(chr(x + shift if ord('a') <= x + shift <= ord('z') else x - ord('z') + ord('a') + shift - 1 if shift > 0 else ord('z') - x + ord('a') + shift + 1 ) for shift in (int(raw_input('Shift: ')),) for x in memoryview(raw_input('Text: ').lower()).tolist())
TrustyTony 888 pyMod Team Colleague Featured Poster

To keep non-alpha letters:

print ''.join(chr(x) if x < ord('a') or x > ord('z') else chr(x + shift if ord('a') <= x + shift <= ord('z') else x - ord('z') + ord('a') + shift - 1 if shift > 0 else ord('z') - x + ord('a') + shift + 1 ) for shift in (int(raw_input('Shift: ')),) for x in memoryview(raw_input('Text: ').lower()).tolist())

Actually original code shifted them by shift:

print ''.join(chr(x + shift) if x < ord('a') or x > ord('z') else chr(x + shift if ord('a') <= x + shift <= ord('z') else x - ord('z') + ord('a') + shift - 1 if shift > 0 else ord('z') - x + ord('a') + shift + 1 ) for shift in (int(raw_input('Shift: ')),) for x in memoryview(raw_input('Text: ').lower()).tolist())

That is however dangerous for characters beside alphabet letters, at it can shift non alphas in alpha letters (which rotate).

TrustyTony 888 pyMod Team Colleague Featured Poster

Last else ord('z') - x + ord('a') + shift + 1 ) should be

else x + 26 + shift

For Python3 you need to add bytes(...., 'ascii') around input to use memoryview.

TrustyTony 888 pyMod Team Colleague Featured Poster

For readability I still recommend for going for multiline solution, here one tested to work in both Python2 and 3.

from string import ascii_lowercase, ascii_uppercase

try:
    # Python 2
    from string import maketrans
except:
    # Python 3
    maketrans = str.maketrans

def ceasar(text, shift=13):
    if shift < 0: shift += 26
    if not shift in ceasar.dict:
        print('Translation table for %i...' % shift)
        c = ascii_lowercase[shift:]+ascii_lowercase[:shift]
        ceasar.dict[shift] = maketrans(ascii_lowercase+ascii_uppercase, c+c.upper())
    return text.translate(ceasar.dict[shift])
ceasar.dict={}

# test
if __name__ == '__main__':
    test_phrase = 'Tony Veijalainen is "pyTony"!'
    for shift in range(-25, 26):
        if shift:
            print('Shift %i' % shift)
            msg  = ceasar(test_phrase, shift)
            print(msg)
            restored = ceasar(msg, -shift)
            assert test_phrase == restored
            print(restored)
            print('')
Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.