简体   繁体   English

在Python中实现Caesar密码算法

[英]Implementing the Caesar cipher algorithm in Python

So I'm trying to do a code that will shift every letter in a word back by a number of letters in the alphabet (wrapping around for the end). 因此,我正在尝试编写一个代码,以将单词中的每个字母向后移字母表中的多个字母(最后环绕)。 For example, if I want to shift by 2 and I input CBE, I should get AZC. 例如,如果我想移动2并输入CBE,我应该得到AZC。 or JOHN into HMFL. 或JOHN进入HMFL。 I got a code to work for only one letter, and I wonder if there's a way to do a nested for loop for python (that works?) 我有一个仅能处理一个字母的代码,而且我想知道是否有一种方法可以为python做一个嵌套的for循环(行得通吗?)

def move(word, shift):
  alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZ"
  original = ""
  for letter in range(26, len(alphabet)):
    if alphabet[letter] == word: #this only works if len(word) is 0, I want to be able to iterate over the letters in word.
        original += alphabet[letter-shift]
  return original

You could start like this 你可以这样开始

def move(word, shift):
    alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
    return "".join([alphabet[alphabet.find(i)-shift] for i in word])

Basically, this list comprehension constructs a list of the single letters. 基本上,此列表理解将构造单个字母的列表。 Then, the index of the letter in the alphabet is found by the .find method. 然后,通过.find方法找到字母表中字母的索引。 The (index - shift) is the desired new index, which is extracted from alphabet. (index-shift)是所需的新索引,它是从字母中提取的。 The resulting list is joined again and returned. 结果列表再次加入并返回。

Note that it does obviously not work on lowercase input strings (if you want that use the str.upper method). 请注意,它显然不适用于小写输入字符串(如果要使用str.upper方法)。 Actually, the word should only consist of letters present in alphabet. 实际上,该单词仅应包含字母中存在的字母。 For sentences the approach needs to treat whitespaces differently. 对于句子,该方法需要区别对待空白。

Don't find the letter in the alphabet that way -- find it with an index operation. 不要以这种方式在字母找到字母-通过索引操作找到它。 Let char be the letter in question: char作为有问题的字母:

alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
...
char_pos = alphabet.index(char)
new_pos = (char_pos - shift) % len(alphabet)
new_char = alphabet[new_pos]

Once you understand this, you can collapse those three lines to a single line. 了解这一点后,您可以将这三行折叠为一行。

Now, to make it operate on an entire word ... 现在,要使其对整个单词都起作用...

new_word = ""
for char in word:
    # insert the above logic
    new_word += new_char

Can you put all those pieces together? 你能把所有这些放在一起吗?

You'll still need your check to see that char is a letter. 您仍然需要检查以确认char是字母。 Also, if you're interested, you can build a list comprehension for all the translated characters and the apply ''.join() to get your new word. 另外,如果您有兴趣,可以为所有已翻译的字符建立列表理解,并应用''.join()获取新单词。

For instance ... 例如 ...

If the letter is in the alphabet (if char in alphabet), shift the given distance and get the new letter, wrapping around the end if needed (% 26). 如果字母在字母表中(如果在字母中为char),则移动给定的距离并获取新字母,如果需要,将其环绕在末尾(%26)。 If it's not a capital letter, then use the original character. 如果不是大写字母,请使用原始字符。

Make a list from all these translations, and then join them into a string. 从所有这些翻译中列出一个清单,然后将它们加入一个字符串中。 Return that string. 返回该字符串。

def move(word, shift):
    alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
    return ''.join([alphabet[(alphabet.find(char) - shift) % 26]
               if char in alphabet else char 
               for char in word])

print move("IBM", 1)
print move("The 1812 OVERTURE is COOL!", 13)

Output: 输出:

HAL
Ghe 1812 BIREGHER is PBBY!
A_VAL = ord('a')

def move(word, shift):
    new_word = ""
    for letter in word:
        new_letter = ord(letter) - shift
        new_word += chr(new_letter) if (new_letter >= A_VAL) else (26 + new_letter)
    return new_word

Note that this will only work for lowercase words. 请注意,这仅适用于小写单词。 As soon as you start mixing upper and lowercase letters you'll need to start checking for them. 一旦开始混合使用大写和小写字母,就需要开始检查它们。 But this is a start. 但这是一个开始。 I discarded your nested loop idea because you should avoid those if at all possible. 我放弃了嵌套循环的想法,因为如果可能的话,您应该避免使用它们。

You could use : chr() give you the character for a ascii number, ord() give you the ascii number for the matching character. 您可以使用: chr()为您提供一个数字的字符, ord()为您提供一个匹配字符的数字。

Here is an old Vigenere project : 这是一个旧的Vigenere项目:

def code_vigenere(ch,cle):
    text = ch.lower()
    clef = cle.lower()
    L = len(cle)
    res = ''

    for i,l in enumerate(text):
        res += chr((ord(l) - 97 + ord(cle[i%L]) - 97)%26 +97)

    return res

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM