# simplifying working caesar cipher

I'm learning python 3 at the moment, so to test the skills i've learned i am trying the puzzles at http://www.pythonchallenge.com/

i've created some code to solve the 2nd puzzle at http://www.pythonchallenge.com/pc/def/map.html (below). it works, but i think that the way i've done it is very convoluted. any suggestions on how to solve the puzzle in a simpler way?

(basically the code needs to substitute each letter in a message to the letter 2 spaces to the right of it e.g. E->G)

I can explain what i have done for those who need it.

My Code:

``````import string
alphabet = string.ascii_lowercase
letter=0
replaceLetter = 2
times=1
message = input()
newMessage=''
while times < 26:
newMessage = message.replace(alphabet[letter], str(replaceLetter)+',')
message = newMessage
letter = letter + 1
replaceLetter = replaceLetter + 1
time = times + 1
if letter == 26:
times = 0
break
newMessage = message.replace('26'+',', 'a')
message = newMessage
newMessage = message.replace('27'+',', 'b')
message = newMessage
number = 25
message = newMessage
while times < 26:
newMessage = message.replace(str(number)+',', str(alphabet[number]))
message = newMessage
letter = letter + 1
number = number - 1
time = times + 1
if number == -1:
times = 0
break
print(newMessage)
``````
-

## migrated from stackoverflow.comDec 3 '11 at 4:37

This question came from our site for professional and enthusiast programmers.

There is a hint in the title of the challenge "What about making trans?". See maketrans. It can be only a couple of lines of code.

-

I would define a shift function that shifted the letters like so:

``````from string import whitespace, punctuation

def shift(c, shift_by = 2):
if c in whitespace + punctuation: return c

upper_ord, lower_ord, c_ord = ord('A'), ord('a'), ord(c)
c_rel = (c_ord - lower_ord) if c_ord >= lower_ord else (c_ord - upper_ord)
offset = lower_ord if c_ord >= lower_ord else upper_ord
return chr(offset + (c_rel + shift_by) % 26)
``````

Then, to translate a message:

``````msg = 'a quick brown fox jumped over the lazy dog'
encoded_msg = ''.join(shift(l) for l in msg)
``````

Alternatively, combine Mark Tolonen's maketrans suggestion with g.d.d's deque suggestion to get:

``````import string
from collections import deque

alphabet = string.ascii_lowercase
alphabet_deque = deque(alphabet)
alphabet_deque.rotate(-2)
rotated_alphabet = ''.join(alphabet_deque)
tbl = string.maketrans(alphabet, rotated_alphabet)
``````

Then, later in the code:

``````msg = 'a quick brown fox jumped over the lazy dog'
encoded_msg = string.translate(msg, tbl)
``````

This second method only works for lowercase letters, but you can always create two separate translation tables -- one for uppercase letters and another for lowercase letters -- to account for case.

Offtopic note: sometimes I wish Python had Smalltalk-like cascaded message sends. Ah well, one can dream.

-

Take a look at the python dictionary. Consider replacing characters?

-

I would do a couple of things differently.

``````import string
from collections import deque

ascii1 = string.ascii_lowercase

# create a deque to simplify rotation.
d = deque(ascii1)
d.rotate(-2)

ascii2 = ''.join(d)

replacements = dict(zip(ascii1, ascii2))

oldmessage = 'This is a string that we want to run through the cipher.'

newmessage = ''.join(replacements.get(c.lower(), c) for c in oldmessage)
# results in 'vjku ku c uvtkpi vjcv yg ycpv vq twp vjtqwij vjg ekrjgt.'
``````

Note that I didn't do anything here to account for casing.

-

this is my code: just use a little of math jijiji

``````def encryptCR(k, msj):
cipher = []
for i in range(len(msj)):
a = (ord(msj[i]) - 97 + k) % 26
a = chr(a + 97)
cipher.append(a)
cipher = "".join(cipher)
return cipher
``````

k is the number of spaces to the rigth and msj is the txt that you need substitude

-
Elegant solution. –  Seralize Aug 31 '12 at 23:22