【问题标题】:Build a dictionary for Caesar cipher为凯撒密码构建字典
【发布时间】:2020-11-12 11:14:54
【问题描述】:

假设输入了一条消息,并且您想通过将单词“up the alphabet”中的每个字母移动 x 个空格来对其进行加密。例如“cat”移动了一个空格变成了“dbu”:

我正在尝试构建一个字典,其中大写和小写字母作为键,重复字母(移动“移位”字母数)作为值。例如 shift=1 d={a:b, b:c...A:B, B:C}。每次“班次”改变时,这个字母都会改变。请让我知道我哪里出错了。请参阅:def build_shift_dict(self, shift) 下面。提前致谢!:

class Message(object):
### DO NOT MODIFY THIS METHOD ###
def __init__(self, text):
    '''
    Initializes a Message object
            
    text (string): the message's text

    a Message object has two attributes:
        self.message_text (string, determined by input text)
        self.valid_words (list, determined using helper function load_words
    '''
    self.message_text = text
    self.valid_words = load_words(WORDLIST_FILENAME)

### DO NOT MODIFY THIS METHOD ###
def get_message_text(self):
    '''
    Used to safely access self.message_text outside of the class
    
    Returns: self.message_text
    '''
    return self.message_text

### DO NOT MODIFY THIS METHOD ###
def get_valid_words(self):
    '''
    Used to safely access a copy of self.valid_words outside of the class
    
    Returns: a COPY of self.valid_words
    '''
    return self.valid_words[:]
    
import string    
def build_shift_dict(self, shift):
    '''
    Creates a dictionary that can be used to apply a cipher to a letter.
    The dictionary maps every uppercase and lowercase letter to a
    character shifted down the alphabet by the input shift. The dictionary
    should have 52 keys of all the uppercase letters and all the lowercase
    letters only.        
    
    shift (integer): the amount by which to shift every letter of the 
    alphabet. 0 <= shift < 26

    Returns: a dictionary mapping a letter (string) to 
             another letter (string). 
    '''
    stringLower = string.ascii_lowercase 
    stringUpper = string.ascii_uppercase
    Alphabet = list(stringLower + stringUpper)
    dictionary = {}
    string2Lower = list(string.ascii_lowercase[shift:] + string.ascii_lowercase[0:shift])
    string2Upper = list(string.ascii_uppercase[shift:] + string.ascii_uppercase[0:shift])
    combinedList = string2Lower.append(string2Upper)
    
    for key in Alphabet: 
        for value in combinedList: 
            dictionary[key] = value 
            combinedList.remove(value) 
             
    return dictionary
    

    
    

def apply_shift(self, shift):
    '''
    Applies the Caesar Cipher to self.message_text with the input shift.
    Creates a new string that is self.message_text shifted down the
    alphabet by some number of characters determined by the input shift        
    
    shift (integer): the shift with which to encrypt the message.
    0 <= shift < 26

    Returns: the message text (string) in which every character is shifted
         down the alphabet by the input shift
    '''
    result=''
    dictionary = self.build_shift_dict(shift)
    messageString = str(Message)
    for letter in messageString:
        if letter in dictionary.keys:
         result += dictionary[i]
    return result

【问题讨论】:

  • 您可能想要删除该行:combinedList.remove(value)。

标签: python encryption


【解决方案1】:

您可以删除很多基于类的东西,因为除了添加样板代码和使事情复杂化之外,它并没有做太多事情。你可以在之后把它放回去,但是在这里我以一种更 Python 的方式为你写了核心功能:

import string

def build_shift_dict(shift):

    alphabet = string.ascii_lowercase + string.ascii_uppercase

    shifted_lower = string.ascii_lowercase[shift:] + string.ascii_lowercase[0:shift]
    shifted_upper = string.ascii_uppercase[shift:] + string.ascii_uppercase[0:shift]

    shifted_alphabet = shifted_lower + shifted_upper

    return {key: value for key, value in zip(alphabet, shifted_alphabet)}

获得shifted_alphabet 后,您可以将zip 与原始字母表一起使用,然后使用Dictionary Comprehension 创建字典。这是一种更 Pythonic 的方式来制作 dict,而不是 for 循环


然后要应用移位,我们可以使用list comprehension 来查找消息中每个字母的字典,并创建一个列表,然后将join 重新组合成一个字符串并返回。

def apply_shift(shift, message):
    dictionary = build_shift_dict(shift)

    return ''.join(dictionary[letter] for letter in message)

然后使用:

>>> print(apply_shift(2, "Hello"))
Jgnnq

在这里-> https://repl.it/@LukeStorry/63042493


更新:您可以通过使用 ordchr 来避免创建和使用字典:

def apply_shift_v2(shift, message):
    return ''.join(chr(ord(letter) + shift) for letter in message)

这具有适用于任何字符的额外好处,而不仅限于您设置字典时使用的字母数字字符。

【讨论】:

  • 感谢卢克,非常有帮助!现在唯一的问题是,对于超出范围的键,我不断收到键错误...我应该将原始字母字符串加倍,以便库中有更多字符吗?看到函数将遍历字典并找到第一个实例,这甚至可以解决问题吗?任何想法将不胜感激!
  • 是的,所以你可以让字典更大一点,添加空格等。然后在传入之前去掉字典中没有的任何字符,或者仔细检查每个字符是in dict 作为键,然后再尝试查找它以防止keyerror
  • 更好的解决方案可能是完全避免使用dicts - 我已经用适用于任何字符的解决方案更新了我的答案。
  • 感谢我更改了代码以创建两个字典。一个用于大写字母,一个用于映射到移位字母的小写字母。然后将其组合成一本字典。如果在 combine_alphabet 列表中,我运行了一个循环以在消息中添加移位的字母。否则添加字母不变(到新字符串)。非常感谢您的时间和耐心!
【解决方案2】:

我的建议是不要创建字典,这会更简单

def apply_shift(shift, letter):
    asci = ord(letter)
    new_ascii = 97 + (asci + shift -97) % 26
    return chr(new_ascii)

print(apply_shift(1, 'z') )

输出:

a

【讨论】:

    猜你喜欢
    • 2016-06-05
    • 2013-10-08
    • 1970-01-01
    • 2014-03-07
    • 2020-05-31
    • 2014-02-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多