2014-02-19 6 views
1

После долгих разочарований, я сделал свой первый Цезарь Decoder :)Как сделать цезарный декодер круговым в Python (2.7)?

Но сейчас проблема в том, чтобы сделать программу круговой ...

Например, если мы хотим сдвигаdoge на 1, нет проблема, это ephf ...

Но как насчет xyz, а смена была 4 ???

Так программирование профи помочь в первый раз новичок аки NEWB из: P Спасибо ...

import string 
def main():   
    inString = raw_input("Please enter the word to be " 
         "translated: ") 
    key = int(raw_input("What is the key value? ")) 

    toConv = [ord(i) for i in inString] #now want to shift it by key 
    toConv = [x+key for x in toConv] 
    #^can use map(lambda x:x+key, toConv) 
    result = ''.join(chr(i) for i in toConv) 

    print "This is the final result due to the shift", result 
+0

Связанный: http://codereview.stackexchange.com/questions/32694/python-caesars-cipher-how-could-i-do-it-better/32696#32696 – kojiro

ответ

0

Просто добавьте key все действительные коды символов, а затем, если добавленная стоимость больше, чем z, modulo с кодом символа z и добавьте его с кодом символа a.

inString, key = "xyz", 4 
toConv = [(ord(i) + key) for i in inString] #now want to shift it by key 
toConv = [(x % ord("z")) + ord("a") if x > ord("z") else x for x in toConv] 
result = ''.join(chr(i) for i in toConv) 
print result # cde 
0

в общем, сделать что-то «обернуть» использовать функцию по модулю (% в Python) с номером вы хотите, чтобы обернуть, и диапазон вы хотите, чтобы обернуть. Например, если бы я хотел печатать цифры от 1 до 10 а bajillion раз, я хотел бы сделать:

i = 0 
while 1: 
    print(i%10+1) 
    # I want to see 1-10, and i=10 will give me 0 (10%10==0), so i%10+1! 
    i += 1 

в этом случае это немного сложнее, потому что вы используете ord, который не имеет хороший счастливый «диапазон» значений , Если вы сделали что-то вроде string.ascii_lowercase вы могли бы сделать ...

import string 
codex = string.ascii_lowercase 

inString = "abcdxyz" 
key = 3 
outString = [codex[(codex.index(char)+key)%len(codex)] for char in inString] 

Однако так как вы используете Ord, мы вроде идущую от ord('A') == 65 до ord('z')==122, поэтому диапазон 0 -> 57 (например, range(58) с константой 65. другими словами:

codex = "ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz" 
# every char for chr(65) -> chr(122) 

codex = ''.join([chr(i+65) for i in range(58)]) # this is the same thing! 

мы можем сделать это вместо того, чтобы, но это будет включать в себя символы [\]^_ `

inString, key = 'abcxyzABCXYZ', 4 
toConv = [(ord(i)+key-65)%58 for i in inString] 
result = ''.join(chr(i+65) for i in toConv) 
print(result) 
# "efgBCDEFG\\]^" 
0

Я бы рекомендовал использовать string.translate().

Таким образом, мы можем сделать следующее:

key = 1 
table = string.maketrans(string.ascii_lowercase + string.ascii_uppercase, string.ascii_lowercase[key:] + string.ascii_lowercase[:key] + string.ascii_uppercase[key:] + string.ascii_uppercase[:key]) 

И тогда мы можем использовать его следующим образом:

'doge'.translate(table) # Outputs 'ephf' 
'Doge'.translate(table) # Outputs 'Ephf' 
'xyz'.translate(table) # Outputs 'yza' 

В частности, это не меняет символы, которые не являются текстовыми строчными или символы верхнего регистра, например числа или пробелы.

'3 2 1 a'.translate(table) # Outputs '3 2 1 b' 
0

Вот код Python, который я написал, чтобы быть понятным. Кроме того, я думаю, что классический цезарский шифр не определил, что делать с пунктуацией; Я думаю, что классические секретные сообщения были необоснованными и содержали только буквы. Я написал это, чтобы обрабатывать классический римский алфавит и передавать любые другие символы без изменений.

В качестве бонуса вы можете использовать этот код со сдвигом 13 для декодирования шуток, закодированных ROT13.

def caesar_ch(ch, shift): 
    """ 
    Caesar cipher for one character. Only shifts 'a' through 'z' 
    and 'A' through 'Z'; leaves other chars unchanged. 
    """ 
    n = ord(ch) 
    if ord('a') <= n <= ord('z'): 
     n = n - ord('a') 
     n = (n + shift) % 26 
     n = n + ord('a') 
     return chr(n) 
    elif ord('A') <= n <= ord('Z'): 
     n = n - ord('A') 
     n = (n + shift) % 26 
     n = n + ord('A') 
     return chr(n) 
    else: 
     return ch 

def caesar(s, shift): 
    """ 
    Caesar cipher for a string. Only shifts 'a' through 'z' 
    and 'A' through 'Z'; leaves other chars unchanged. 
    """ 
    return ''.join(caesar_ch(ch, shift) for ch in s) 

if __name__ == "__main__": 
    assert caesar("doge", 1) == "ephf" 

    assert caesar("xyz", 4) == "bcd" 

    assert caesar("Veni, vidi, vici.", 13) == "Irav, ivqv, ivpv." 

Часть в конце является «самотестированием» для кода. Если вы запустите это как автономную программу, она проверит себя и «утвердит», если тест завершится с ошибкой.

Если у вас есть какие-либо вопросы по поводу этого кода, просто спросите, и я объясню.

0

Я знаю, что это своего рода старая тема, но я только что работал над ней сегодня. Я нашел ответы в этой теме полезными, но все они, похоже, использовали решение для цикла. Я понял способ достижения той же цели, просто используя оператор модуля (остатка) (%). Это позволяет номеру оставаться в пределах диапазона таблицы и перемещаться. Это также позволяет легко декодировать.

# advCeaser.py 
# This program uses a ceaser cypher to encode and decode messages 
import string 

def main(): 
    # Create a table to reference all upper, lower case, numbers and common punctuation. 
    table = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz1234567890,[email protected]' 

    print 'This program accepts a message and a key to encode the message.' 
    print 'If the encoded message is entered with the negative value of the key' 
    print 'The message will be decoded!' 

    # Create accumulator to collect coded message 
code ='' 

    # Get input from user: Message and encode key 
    message = raw_input('Enter the message you would like to have encoded:') 
    key = input('Enter the encode or decode key: ') 

    # Loop through each character in the message 
    for ch in message: 
     # Find the index of the char in the table add the key value 
     # Then use the remainder function to stay within range of the table. 
     index = ((table.find(ch)+key)%len(table)) 

     # Add a new character to the code using the index 
     code = code + table[index] 

    # Print out the final code 
    print code 

main() 

Результат кодирования и декодирования выглядит следующим образом.

закодировать:

This program accepts a message and a key to encode the message. 
If the encoded message is entered with the negative value of the key 
The message will be decoded! 
Enter the message you would like to have encoded:The zephyr blows from the east to the west! 
Enter the encode or decode key: 10 
croj0ozr92jlvy73jp2ywj4rojok34j4yj4roj7o34G 

декодировании:

This program accepts a message and a key to encode the message. 
If the encoded message is entered with the negative value of the key 
The message will be decoded! 
Enter the message you would like to have encoded:croj0ozr92jlvy73jp2ywj4rojok34j4yj4roj7o34G 
Enter the encode or decode key: -10 
The zephyr blows from the east to the west! 

Извините, если мое форматирование выглядит catywompus я буквально нашел StackOverflow вчера! Да, я буквально имею в виду буквально :)