2012-01-16 89 views
10

Tôi đang cố tạo một hàm mã Caesar đơn giản bằng Python thay đổi các chữ cái dựa trên đầu vào từ người dùng và tạo chuỗi cuối cùng, mới ở cuối. Vấn đề duy nhất là văn bản mã hóa cuối cùng chỉ hiển thị ký tự được dịch chuyển cuối cùng, không phải toàn bộ chuỗi với tất cả các ký tự được dịch chuyển.Chức năng mã hóa Caesar trong Python

Dưới đây là mã của tôi:

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) 
+0

[Python 3 Caesar cipher implementation] (http://stackoverflow.com/a/26371777/4279) – jfs

Trả lời

15

Bạn cần phải di chuyển cipherText = "" trước khi bắt đầu vòng lặp for. Bạn sẽ đặt lại nó mỗi lần qua vòng lặp.

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 
+0

Xin lỗi, không nhận thấy câu trả lời của bạn, không có thông báo nào trong khi tôi viết thư. +1 –

2

Vấn đề là bạn thiết lập bản mã để chuỗi rỗng tại mỗi lần lặp chu kỳ, dòng

cipherText = "" 

phải được di chuyển trước khi vòng lặp.

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

Là người khác nếu ch.isalpha() bạn có thể đặt finalLetter=ch.

Bạn nên xóa dòng: cipherText = ""

Chúc mừng.

1

Như @ I82much đã nói, bạn cần phải thực hiện cipherText = "" ngoài vòng lặp của mình. Đặt nó ở đầu hàm. Ngoài ra, chương trình của bạn có một lỗi mà sẽ gây ra nó để tạo ra lỗi mã hóa khi bạn nhận được chữ in hoa làm đầu vào. Hãy thử:

if ch.isalpha(): 
     finalLetter = chr((ord(ch.lower()) - 97 + shift) % 26 + 97) 
34

Tôi nhận thấy câu trả lời này không thực sự trả lời câu hỏi của bạn, nhưng tôi nghĩ điều đó cũng hữu ích. Dưới đây là một cách khác để triển khai mật mã caesar bằng các phương thức chuỗi:

def caesar(plaintext, shift): 
    alphabet = string.ascii_lowercase 
    shifted_alphabet = alphabet[shift:] + alphabet[:shift] 
    table = string.maketrans(alphabet, shifted_alphabet) 
    return plaintext.translate(table) 

Thực tế, vì các phương thức chuỗi được thực hiện trong C, chúng ta sẽ thấy sự gia tăng hiệu suất với phiên bản này. Đây là những gì tôi sẽ xem xét cách 'pythonic' để làm điều này.

+3

Giải pháp ở trên hoạt động trong Python 2 nhưng trong Python 3 sử dụng 'str.maketrans()' thay vì 'string.maketrans()'. – cclauss

+0

đây là một thực hiện tốt đẹp của Caesar Cipher –

1

Được chỉ định bởi những người khác, bạn đã đặt lại cipherText trong vòng lặp của vòng lặp for. Đặt cipherText trước khi bắt đầu vòng lặp for sẽ giải quyết vấn đề của bạn.

Ngoài ra, có một cách tiếp cận thay thế để giải quyết vấn đề này bằng cách sử dụng thư viện Chuẩn của Python. Thư viện chuẩn Python định nghĩa một hàm maketrans() và một phương thức dịch hoạt động trên các chuỗi.

Hàm maketrans() tạo bảng dịch có thể được sử dụng với phương thức dịch để thay đổi một tập hợp các ký tự thành một tập hợp khác một cách hiệu quả hơn. (Trích dẫn từ Thư viện chuẩn Python bằng Ví dụ).

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

Pin bao gồm

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 cập nhật

Các fine docs nói

[Bây giờ rot_13] codec cung cấp biến đổi văn bản: một ánh xạ str thành str. Nó không được hỗ trợ bởi str.encode() (chỉ tạo ra đầu ra byte).

Hoặc, nói cách khác, bạn phải nhập encode từ các module codecs và sử dụng nó với chuỗi được mã hóa như là đối số đầu tiên của nó

from codecs import decode 
... 
    print(encode(phrase, 'rot13')) 
3

Sử dụng một số thủ thuật số 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) 
0
from string import ascii_lowercase as alphabet 

class CaesarCypher: 
    alpha_len = len(alphabet) 
    min_guess_rate = 0.2 

Mã hóa và giải mã cũng giống nhau. khi bạn muốn giải mã ví dụ với ca 10 có nghĩa là bạn có thể mã hóa nó với ca. 26 - 10. Trong trường hợp này, chu kỳ sẽ lặp lại nếu bạn chuyển toàn bộ bảng chữ cái, nó sẽ giống nhau. Ngoài ra ở đây tôi đã tiến hành trường hợp trên và không phải ký tự chữ hoa

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) 

tất cả các mã hóa đều được sử dụng nhiều nhất.

def _encrypt_letter(self, letter, offset=0): 
     position = (alphabet.find(letter) + offset) % self.alpha_len 
     return alphabet[position] 

phần này dành cho lực lượng broot và đoán tần suất từ ​​điển.

@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 
+0

Bạn có chắc bạn đang trả lời câu hỏi cụ thể được hỏi bởi OP? Anh ta không yêu cầu cách viết lại mã, anh ta chỉ muốn giúp đỡ tìm lỗi. –

0

Ở đây, một cách thêm chức năng: (nếu bạn sử dụng thay đổi tôi để mã hóa, sau đó sử dụng -i để giải mã)

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 
     ]) 
-3
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() 
-1
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 
+0

Vui lòng sử dụng liên kết [chỉnh sửa] để giải thích cách mã này hoạt động và không chỉ cung cấp mã, vì giải thích có nhiều khả năng giúp người đọc trong tương lai. Xem thêm [trả lời]. [nguồn] (http://stackoverflow.com/users/5244995) –

0

theo tôi câu trả lời này là hữu ích cho bạn:

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) 

Chức năng này shif ts tất cả các chữ cái theo đúng theo khóa đã cho.

0
>>> 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!' 
0

Tôi có một thời gian khó nhớ char sang int chuyển đổi vì vậy đây có thể được tối ưu hóa

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

    return decrypted 
1
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() 
0

Tại sao không sử dụng chức năng đảo ngược trên đầu vào thay đổi, và và tham gia vào plain_text với ca làm việc và nhập nó làm văn bản mật mã:

Plain = int(input("enter a number ")) 
Rev = plain[::-1] 
Cipher = " ".join(for cipher_text in Rev)