2012-01-16 34 views
10

Estoy tratando de crear una función de Cifrado César simple en Python que cambie las letras en función de la entrada del usuario y cree una cadena final y nueva al final. El único problema es que el texto de cifrado final muestra solo el último carácter desplazado, no una cadena completa con todos los caracteres desplazados.Función de cifrado César en Python

Aquí está mi código:

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 César aplicación de cifrado] (http://stackoverflow.com/a/26371777/4279) – jfs

Respuesta

15

Es necesario mover cipherText = "" antes del inicio del bucle. Lo está restableciendo cada vez que pasa el ciclo.

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

Lo siento, no he notado su respuesta, no había ninguna notificación mientras escribía la mía. +1 –

2

El problema es que se establece a texto cifrado cadena vacía en cada iteración del ciclo, la línea

cipherText = "" 

se debe mover antes del bucle.

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) 

Como una cosa que si se puede poner ch.isalpha()finalLetter=ch.

debe quitar la línea: cipherText = ""

Saludos.

1

Como dijo @ I82much, debe tomar cipherText = "" fuera del bucle for. Colóquelo al comienzo de la función. Además, su programa tiene un error que hará que genere errores de encriptación cuando recibe letras mayúsculas como entrada. Pruebe:

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

Me doy cuenta de que esta respuesta realmente no responde a su pregunta, pero creo que de todos modos es útil. Aquí hay una forma alternativa de implementar el cifrado César con métodos de cadena:

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

De hecho, ya que los métodos de cuerda se implementan en C, vamos a ver un aumento en el rendimiento con esta versión. Esto es lo que yo consideraría la forma "pitónica" de hacer esto.

+3

La solución anterior funciona en Python 2, pero en Python 3 use 'str.maketrans()' en lugar de 'string.maketrans()'. – cclauss

+0

esta es una buena implementación de Caesar Cipher –

1

Como señalaron otros, estaba reiniciando el texto cifrado en la iteración del ciclo for. Colocar cipherText antes del inicio del ciclo for resolverá su problema.

Además, hay un enfoque alternativo para resolver este problema utilizando la biblioteca estándar de Python. Python Standard Library define una función maketrans() y un método de traducción que opera en cadenas.

La función maketrans() crea tablas de traducción que se pueden usar con el método translate para cambiar un conjunto de caracteres a otro de manera más eficiente. (Citado de The Python Standard Library por Ejemplo).

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

Pilas incluidas

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 actualización

El fine docs dicen

[Ahora el rot_13] códec proporciona un texto transformar: un mapeo str-str. No es compatible con str.encode() (que solo produce salida de bytes).

O, en otras palabras, usted tiene que importar encode del módulo codecs y utilizarlo con la cadena a ser codificada como primer argumento

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

El uso de algunos números ASCII trucos:

# 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 

Encriptación y desencriptación es lo mismo. cuando desee descifrar, por ejemplo, con el turno 10, significa que puede encriptarlo con el turno 26 - 10. En este caso, el ciclo se repetirá; si va a cambiar todo el alfabeto, será el mismo. También aquí Me he proceder mayúsculas y caracteres no

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) 

toda la encriptación va aquí en más.

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

esta parte es para la fuerza Broot y supongo throug frecuencia diccionario.

@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

¿Estás seguro de que estás respondiendo la pregunta específica del OP? No estaba pidiendo una forma de reescribir el código, solo quería ayuda para encontrar el error. –

0

Aquí, una manera más funcional: (si utiliza turno i para codificar, a continuación, utilizar -i para decodificar)

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

Utilice el enlace [editar] para explicar cómo funciona este código y no solo proporcione el código, ya que una explicación es más probable que ayude a los lectores futuros. Ver también [respuesta]. [fuente] (http://stackoverflow.com/users/5244995) –

0

en mi opinión esta respuesta es útil para usted:

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) 

Esta función shift ts toda la letra a la derecha según la clave dada.

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

que tienen dificultades para recordar el char a int conversiones por lo que este podría ser optimizado

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

Por qué no utilizar la función inversa de la entrada de desplazamiento, y unirte a la texto_plano con el cambio, y la entrada como el texto cifrado:

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