19

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)
4

26 に答える 26

57

この回答があなたの質問に実際に答えているわけではないことは承知していますが、とにかく役立つと思います。文字列メソッドを使用してシーザー暗号を実装する別の方法を次に示します。

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 で実装されているため、このバージョンではパフォーマンスが向上します。これは、これを行う「pythonic」方法と私が考えるものです。

于 2012-01-17T13:35:10.610 に答える
20

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
于 2012-01-16T22:07:58.703 に答える
5

いくつかの 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)
于 2016-01-03T16:34:22.493 に答える
3

問題は、サイクルの反復ごとに cipherText を空の文字列に設定することです。

cipherText = ""

ループの前に移動する必要があります。

于 2012-01-16T22:09:49.827 に答える
2

ここで、より機能的な方法: (シフト 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 
        ])
于 2016-10-13T23:37:27.577 に答える
1

cipherText = ""@ I82muchが言ったように、forループの外に出る必要があります。関数の先頭に配置します。また、プログラムには、入力として大文字を取得したときに暗号化エラーを生成するバグがあります。試す:

    if ch.isalpha(): 
        finalLetter = chr((ord(ch.lower()) - 97 + shift) % 26 + 97)
于 2012-01-17T02:47:48.607 に答える
1

char から int への変換を覚えるのに苦労しているので、これを最適化できます

def decryptCaesar(encrypted, shift):
    minRange = ord('a')
    decrypted = ""
    for char in encrypted:
        decrypted += chr(((ord(char) - minRange + shift) % 26) + minRange)

    return decrypted
于 2017-09-29T20:51:40.953 に答える
0
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
于 2016-09-08T09:52:43.117 に答える
0
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
于 2017-03-29T13:01:37.650 に答える
-1
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()
于 2016-11-09T13:40:09.970 に答える