Функция Цезаря Шифра в Python - PullRequest
15 голосов
/ 17 января 2012

Я пытаюсь создать простую функцию 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)

Ответы [ 19 ]

41 голосов
/ 17 января 2012

Я понимаю, что этот ответ на самом деле не отвечает на ваш вопрос, но я думаю, что он все равно полезен.Вот альтернативный способ реализации Цезаря с помощью строковых методов:

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, мы увидим увеличение производительности в этой версии.Это то, что я бы назвал «питоническим» способом сделать это.

15 голосов
/ 17 января 2012

Вам нужно переместиться на 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 голосов
/ 03 января 2016

Использование некоторых числовых трюков ascii:

# 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)
2 голосов
/ 18 марта 2015

Батарейки в комплекте

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

Прекрасные документы 1014 * скажем

[Теперь кодек rot_13] обеспечивает преобразование текста: отображение str в str. Он не поддерживается str.encode() (который выводит только байты).

Или, другими словами, вы должны импортировать encode из модуля codecs и использовать его со строкой, которая должна быть закодирована в качестве первого аргумента

from codecs import decode
...
    print(encode(phrase, 'rot13'))
2 голосов
/ 07 апреля 2013

Как указывалось другими, вы сбрасывали cipherText в итерации цикла for.Размещение cipherText до начала цикла for решит вашу проблему.

Кроме того, существует альтернативный подход к решению этой проблемы с использованием стандартной библиотеки Python.Стандартная библиотека Python определяет функцию maketrans () и метод translate, который работает со строками.

Функция maketrans () создает таблицы перевода, которые можно использовать с методом translate для замены одного набора символов на другой, болееэффективно.(Цитируется из стандартной библиотеки 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)
2 голосов
/ 17 января 2012

Проблема заключается в том, что вы устанавливаете для cipherText пустую строку на каждой итерации цикла, строка

cipherText = ""

должна быть перемещена перед циклом.

1 голос
/ 17 января 2012

Как сказал @ I82, вам нужно взять cipherText = "" за пределами цикла for. Поместите это в начало функции. Кроме того, в вашей программе есть ошибка, из-за которой она генерирует ошибки шифрования при вводе заглавных букв. Попробуйте:

    if ch.isalpha(): 
        finalLetter = chr((ord(ch.lower()) - 97 + shift) % 26 + 97)
1 голос
/ 08 февраля 2019

Это улучшенная версия кода в ответе @ 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 библиотека

1 голос
/ 12 октября 2017
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()
1 голос
/ 14 октября 2016

Вот более функциональный способ: (если вы используете shift i для кодирования, то используйте -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 
        ])
...