Caesar Cipher Function in Python
Solution 1
I realize that this answer doesn't really answer your question, but I think it's helpful anyway. Here's an alternative way to implementing the caesar cipher with string methods:
def caesar(plaintext, shift):
alphabet = string.ascii_lowercase
shifted_alphabet = alphabet[shift:] + alphabet[:shift]
table = string.maketrans(alphabet, shifted_alphabet)
return plaintext.translate(table)
In fact, since string methods are implemented in C, we will see an increase in performance with this version. This is what I would consider the 'pythonic' way of doing this.
Solution 2
You need to move cipherText = ""
before the start of the for loop. You're resetting it each time through the loop.
def caesar(plainText, shift):
cipherText = ""
for ch in plainText:
if ch.isalpha():
stayInAlphabet = ord(ch) + shift
if stayInAlphabet > ord('z'):
stayInAlphabet -= 26
finalLetter = chr(stayInAlphabet)
cipherText += finalLetter
print "Your ciphertext is: ", cipherText
return cipherText
Solution 3
This is an improved version of the code in the answer of @amillerrhodes that works with different alphabets, not just lowercase:
def caesar(text, step, alphabets):
def shift(alphabet):
return alphabet[step:] + alphabet[:step]
shifted_alphabets = tuple(map(shift, alphabets))
joined_aphabets = ''.join(alphabets)
joined_shifted_alphabets = ''.join(shifted_alphabets)
table = str.maketrans(joined_aphabets, joined_shifted_alphabets)
return text.translate(table)
Example of usage:
>>> import string
>>> alphabets = (string.ascii_lowercase, string.ascii_uppercase, string.digits)
>>> caesar('Abc-xyZ.012:789?жñç', step=4, alphabets=alphabets)
'Efg-bcD.456:123?жñç'
References:
Docs on str.maketrans
.
Docs on str.translate
.
Docs on the string
library
Solution 4
Using some ascii number tricks:
# See http://ascii.cl/
upper = {ascii:chr(ascii) for ascii in range(65,91)}
lower = {ascii:chr(ascii) for ascii in range(97,123)}
digit = {ascii:chr(ascii) for ascii in range(48,58)}
def ceasar(s, k):
for c in s:
o = ord(c)
# Do not change symbols and digits
if (o not in upper and o not in lower) or o in digit:
yield o
else:
# If it's in the upper case and
# that the rotation is within the uppercase
if o in upper and o + k % 26 in upper:
yield o + k % 26
# If it's in the lower case and
# that the rotation is within the lowercase
elif o in lower and o + k % 26 in lower:
yield o + k % 26
# Otherwise move back 26 spaces after rotation.
else: # alphabet.
yield o + k % 26 -26
x = (''.join(map(chr, ceasar(s, k))))
print (x)
Solution 5
Batteries included
while 1:
phrase = raw_input("Could you please give me a phrase to encrypt?\n")
if phrase == "" : break
print "Here it is your phrase, encrypted:"
print phrase.encode("rot_13")
print "Have a nice afternoon!"
https://docs.python.org/2/library/codecs.html#python-specific-encodings
Python 3 update
The fine docs say
[Now the
rot_13
] codec provides a text transform: astr
tostr
mapping. It is not supported bystr.encode()
(which only produces bytes output).
Or, in other words, you have to import encode
from the codecs
module and use it with the string to be encoded as its first argument
from codecs import decode
...
print(encode(phrase, 'rot13'))
![Admin](/assets/logo_square_200-5d0d61d6853298bd2a4fe063103715b4daf2819fc21225efa21dfb93e61952ea.png)
Admin
Updated on July 05, 2022Comments
-
Admin almost 2 years
I'm trying to create a simple Caesar Cipher function in Python that shifts letters based on input from the user and creates a final, new string at the end. The only problem is that the final cipher text shows only the last shifted character, not an entire string with all the shifted characters.
Here's my code:
plainText = raw_input("What is your plaintext? ") shift = int(raw_input("What is your shift? ")) def caesar(plainText, shift): for ch in plainText: if ch.isalpha(): stayInAlphabet = ord(ch) + shift if stayInAlphabet > ord('z'): stayInAlphabet -= 26 finalLetter = chr(stayInAlphabet) cipherText = "" cipherText += finalLetter print "Your ciphertext is: ", cipherText return cipherText caesar(plainText, shift)
-
Fabio says Reinstate Monica almost 8 yearsAre you sure you are answering the specific question asked by the OP? He wasn't asking for a way to rewrite the code, he just wanted some help at finding the bug.
-
cclauss over 7 yearsThe solution above works in Python 2 but in Python 3 use
str.maketrans()
instead ofstring.maketrans()
. -
Jed Fox about 7 yearsPlease use the edit link to explain how this code works and don't just give the code, as an explanation is more likely to help future readers. See also How to Answer. source
-
Georgy over 5 yearsImproved version of this code for the case of several alphabets (lowercase, uppercase, digits, etc.): stackoverflow.com/a/54590077/7851470
-
Arnb over 4 yearsHere s is the encrypted string and k is the shift in integer.
-
Chris about 4 yearsCode dumps without any explanation are rarely helpful. Stack Overflow is about learning, not providing snippets to blindly copy and paste. Please edit your question and explain how it works better than what the OP provided.
-
Amitai Irron about 4 yearsYou should also relate to the code provided by the asker of the question. It looks like their code is very close to working (even if being a bit un-elegant in places), so relating to it would strengthen learning.
-
Nick K9 over 3 yearsThis is a really nice approach which is configurable and avoids mod arithmetic. Very pythonic, thanks!
-
Nick K9 over 3 yearsOne downside, though, is that it doesn't allow character decrementing. To reverse the operation you would have to increment by the complement of the initial encryption.