Функция Cesar Cipher в Python
Я пытаюсь создать простую функцию Caesar Cipher в Python, которая сдвигает буквы на основе ввода от пользователя и создает окончательную новую строку в конце. Единственная проблема заключается в том, что окончательный текст шифрования показывает только последний сдвинутый символ, а не целую строку со всеми сдвинутыми символами.
Здесь мой код:
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)
Ответы
Ответ 1
Я понимаю, что этот ответ на самом деле не отвечает на ваш вопрос, но я думаю, что это все равно полезно. Здесь альтернативный способ реализации цезарного шифрования со строковыми методами:
def caesar(plaintext, shift):
alphabet = string.ascii_lowercase
shifted_alphabet = alphabet[shift:] + alphabet[:shift]
table = string.maketrans(alphabet, shifted_alphabet)
return plaintext.translate(table)
На самом деле, поскольку строковые методы реализованы на C, мы увидим увеличение производительности с этой версией. Это то, что я считаю "питоническим" способом этого.
Ответ 2
Вам нужно переместить cipherText = ""
до начала цикла for. Вы каждый раз перезапускаете его через цикл.
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
Ответ 3
Батареи включены
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
тонкие документы говорят
[Теперь кодек rot_13
] предоставляет текстовое преобразование: a str
to str
. Он не поддерживается str.encode()
(который генерирует только байты).
Или, другими словами, вам нужно импортировать encode
из модуля codecs
и использовать его со строкой, которая должна быть закодирована как ее первый аргумент
from codecs import decode
...
print(encode(phrase, 'rot13'))
Ответ 4
Использование некоторых атрийных трюков:
# 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 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 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)
Ответ 5
Проблема заключается в том, что вы устанавливаете cipherText для пустых строк на каждой итерации цикла, строка
cipherText = ""
должен быть перемещен до цикла.
Ответ 6
Как указывалось другими, вы перезагружали cipherText в итерации цикла for. Размещение cipherText до начала цикла for решит вашу проблему.
Кроме того, существует альтернативный подход к решению этой проблемы с использованием библиотеки Python Standard. Стандартная библиотека Python определяет функцию maketrans() и метод translate, который работает с строками.
Функция maketrans() создает таблицы перевода, которые могут использоваться с методом перевода, чтобы более эффективно изменять один набор символов на другой. (Цитируется из стандартной библиотеки Python по примеру).
import string
def caesar(plaintext, shift):
shift %= 26 # Values greater than 26 will wrap around
alphabet_lower = string.ascii_lowercase
alphabet_upper = string.ascii_uppercase
shifted_alphabet_lower = alphabet_lower[shift:] + alphabet_lower[:shift]
shifted_alphabet_upper = alphabet_upper[shift:] + alphabet_upper[:shift]
alphabet = alphabet_lower + alphabet_upper
shifted_alphabet = shifted_alphabet_lower + shifted_alphabet_upper
table = string.maketrans(alphabet, shifted_alphabet)
return plaintext.translate(table)
Ответ 7
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)
#####HERE YOU RESET CIPHERTEXT IN EACH ITERATION#####
cipherText = ""
cipherText += finalLetter
print "Your ciphertext is: ", cipherText
return cipherText
caesar(plainText, shift)
В качестве else к if ch.isalpha()
вы можете поместить finalLetter=ch
.
Вы должны удалить строку: cipherText = ""
Приветствия.
Ответ 8
Как @I82much сказал, вам нужно взять cipherText = ""
за пределами вашего цикла for. Поместите его в начале функции. Кроме того, ваша программа имеет ошибку, которая заставит ее генерировать ошибки шифрования, когда вы получите заглавные буквы в качестве входных данных. Попробуйте:
if ch.isalpha():
finalLetter = chr((ord(ch.lower()) - 97 + shift) % 26 + 97)
Ответ 9
Здесь более функциональный способ:
(если вы используете shift я для кодирования, тогда используйте -i для декодирования)
def ceasar(story, shift):
return ''.join([ # concentrate list to string
(lambda c, is_upper: c.upper() if is_upper else c) # if original char is upper case than convert result to upper case too
(
("abcdefghijklmnopqrstuvwxyz"*2)[ord(char.lower()) - ord('a') + shift % 26], # rotate char, this is extra easy since Python accepts list indexs below 0
char.isupper()
)
if char.isalpha() else char # if not in alphabet then don't change it
for char in story
])
Ответ 10
>>> def rotate(txt, key):
... def cipher(i, low=range(97,123), upper=range(65,91)):
... if i in low or i in upper:
... s = 65 if i in upper else 97
... i = (i - s + key) % 26 + s
... return chr(i)
... return ''.join([cipher(ord(s)) for s in txt])
# test
>>> rotate('abc', 2)
'cde'
>>> rotate('xyz', 2)
'zab'
>>> rotate('ab', 26)
'ab'
>>> rotate('Hello, World!', 7)
'Olssv, Dvysk!'
Ответ 11
def encrypt():
plainText = input("What is your plaintext? ")
shift = int(input("What is your 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,"with a shift of",shift)
def decrypte():
encryption=input("enter in your encrypted code")
encryption_shift=int(input("enter in your encryption shift"))
cipherText1 = ""
for c in encryption:
if c.isalpha():
stayInAlphabet1 = ord(c) - encryption_shift
if stayInAlphabet1 > ord('z'):
stayInAlphabet1 += 26
finalLetter1 = chr(stayInAlphabet1)
cipherText1 += finalLetter1
print ("Your ciphertext is: ", cipherText1,"with negative shift of",encryption_shift)
from tkinter import *
menu=Tk()
menu.title("menu")
menu.geometry("300x300")
button1= Button(menu,text="encrypt",command=encrypt)
button1.pack()
button2= Button(menu,text="decrypt",command=decrypte)
button2.pack()
button3= Button(menu,text="exit",command=exit)
button3.pack()
menu.mainloop()
Ответ 12
Это улучшенная версия кода в ответе @amillerrhodes, которая работает с разными алфавитами, а не только с нижним регистром:
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)
Пример использования:
>>> import string
>>> alphabets = (string.ascii_lowercase, string.ascii_uppercase, string.digits)
>>> caesar('Abc-xyZ.012:789?жñç', step=4, alphabets=alphabets)
'Efg-bcD.456:123?жñç'
Ссылки:
Документы на str.maketrans
.
Документы на str.translate
.
Документы по библиотеке string
Ответ 13
from string import ascii_lowercase as alphabet
class CaesarCypher:
alpha_len = len(alphabet)
min_guess_rate = 0.2
Шифрование и дешифрование - это один и тот же материал. когда вы хотите дешифровать, например, с помощью сдвига 10, что означает, что вы можете зашифровать его со сдвигом 26-10. В этом случае цикл повторится, если вы собираетесь сдвинуть весь алфавит, это будет одинаково. Также здесь я делаю верхний регистр и не символы
def __call__(self, text, offset, encrypt=True):
if not encrypt:
offset = self.alpha_len - offset
result = []
for letter in text:
if not letter.isalpha():
result.append(letter)
continue
letter_to_process = letter.lower()
processed_letter = self._encrypt_letter(letter_to_process, offset)
if letter.isupper():
processed_letter = processed_letter.upper()
result.append(processed_letter)
return ''.join(result)
все шифрование идет здесь не более.
def _encrypt_letter(self, letter, offset=0):
position = (alphabet.find(letter) + offset) % self.alpha_len
return alphabet[position]
эта часть предназначена для силовой нагрузки и догадывается, что словарная частота.
@staticmethod
def __how_many_do_i_know(text):
clean_words = filter(lambda x: x.isalpha(), text.split())
clean_words = ['\'{}\''.format(x) for x in clean_words]
cursor = conn.cursor()
query = 'SELECT COUNT(*) FROM mydictionary WHERE word IN ({})'.format(",".join(clean_words))
cursor.execute(query)
response = cursor.fetchone()[0]
return response / len(clean_words)
def guess_encode(self, text):
options = [self(text, offset, encrypt=False) for offset in range(self.alpha_len)]
best_option = [self.__how_many_do_i_know(option) for option in options]
best_key, guess_rate = max(enumerate(best_option), key=lambda x: x[-1])
guess_text = options[best_key]
return best_key, guess_rate, guess_text
Ответ 14
import string
wrd=raw_input("Enter word").lower()
fwrd=""
for let in wrd:
fwrd+=string.ascii_lowercase[(string.ascii_lowercase).index(let)+3]
print"Original word",wrd
print"New word",fwrd
Ответ 15
согласно мне, этот ответ полезен для вас:
def casear(a,key):
str=""
if key>26:
key%=26
for i in range(0,len(a)):
if a[i].isalpha():
b=ord(a[i])
b+=key
#if b>90: #if upper case letter ppear in your string
# c=b-90 #if upper case letter ppear in your string
# str+=chr(64+c) #if upper case letter ppear in your string
if b>122:
c=b-122
str+=chr(96+c)
else:
str+=chr(b)
else:
str+=a[i]
print str
a=raw_input()
key=int(input())
casear(a,key)
Эта функция сдвигает все буквы вправо в соответствии с заданной клавишей.
Ответ 16
Мне сложно запомнить преобразования char to int, чтобы это можно было оптимизировать
def decryptCaesar(encrypted, shift):
minRange = ord('a')
decrypted = ""
for char in encrypted:
decrypted += chr(((ord(char) - minRange + shift) % 26) + minRange)
return decrypted
Ответ 17
Почему бы не использовать функцию reverse на вводе сдвига, а также соединить plain_text со сдвигом и ввести его как текст шифрования:
Plain = int(input("enter a number "))
Rev = plain[::-1]
Cipher = " ".join(for cipher_text in Rev)
Ответ 18
message = 'The quick brown fox jumped over the lazy dog. 1234567890 [email protected]#$%^&*()_+-'
encrypted = ''.join(chr(ord(char)+3) for char in message)
decrypted = ''.join(chr(ord(char)-3) for char in encrypted)
print(encrypted)
print(decrypted)
# Wkh#txlfn#eurzq#ir{#mxpshg#ryhu#wkh#od}|#grj1#456789:;<3#$C&'(a)-+,b.0
# The quick brown fox jumped over the lazy dog. 1234567890 [email protected]#$%^&*()_+-
Ответ 19
key = 3
def wub():
def choice():
choice = input("Do you wish to Encrypt of Decrypt?")
choice = choice.lower()
if choice == "e" or "encrypt":
return choice
elif choice == "d" or "decrypt":
return choice
else:
print("Invalid response, please try again.")
choice()
def message():
user = input("Enter your message: ")
return user
def waffle(choice, message, key):
translated = ""
if choice == "e" or "encrypt":
for character in message:
num = ord(character)
num += key
translated += chr(num)
derek = open('Encrypted.txt', 'w')
derek.write(translated)
derek.close()
return translated
else:
for character in message:
num = ord(character)
num -= key
translated += chr(num)
return translated
choice = choice() #Runs function for encrypt/decrypt selection. Saves choice made.
message = message() #Run function for user to enter message. Saves message.
final = waffle(choice, message, key) #Runs function to translate message, using the choice, message and key variables)
print("\n Operation complete!")
print(final)
wub()