首页 > 解决方案 > 在使用凯撒密码加密文本的程序中出现错误

问题描述

Caesar Cipher 是一种简单的加密方法,可以将字符前面的多个位置移动。例如,旋转为 1 的 ABC 将是 BCD。然而,在这个程序中,所有字符的列表都包含随机顺序的特殊字符,即

1234567890-=qwertyuiopasdfghjklzxcvbnm,./~!@#$%^&*()_+|\\{}[]:;\'"QWERTYUIOPASDFGHJKLZXCVBNM

因此,它更像是一种自定义密码,但遵循凯撒密码的原则,可以使用我在同一文本上制作的 2 个函数(encode() 和 decode())来测试代码,如果给出的输出是与输入相同,这意味着它可以工作。我得到了一些旋转数字的输出,但是一些数字,比如 70,给了我一个错误。我写的代码是:

characters = '`1234567890-=qwertyuiopasdfghjklzxcvbnm,./~!@#$%^&*()_+|\\{}[]:;\'"QWERTYUIOPASDFGHJKLZXCVBNM' # All characters in a string, no specific order
key_raw = 70 # One of the keys that gives me an error.
def encode(text, key): # Function that takes in two inputs: Text and key, which is the number of characters to shift forward
    output, text = '', str(text)
    limit = len(characters)
    while key > limit:
        key -= limit # This is my attempt to simplify the key
    for i in text:
        if i in characters:
            output += characters[characters.index(i)+key] # If i is in characters, the rotated character is concatenated to the output
        else:
            output += i # Otherwise, it directly adds the text
    return output
def decode(text, key): # Same thing, except key is subtracted from the index of i in key, as to decrypt it
    output, text = '', str(text)
    limit = len(characters)
    while key > limit:
        key -= limit
    for i in text:
        if i in characters:
            output += characters[characters.index(i)-key]
        else:
            output += i
    return output
print(encode('Why do I get String_Index_Out_Of_Range?', key_raw))

请让我知道我在哪里犯了错误。

标签: pythonencryption

解决方案


考虑当您收到characters.index(i)+keywhere index is the last symbol in时会发生什么characters

简而言之,您的凯撒密码缺少模运算。

但是,为了使它更有用,我们仍然可以尝试进一步改进您的代码。

让我们从构建字符串的方式开始。当涉及到大字符串时,您当前使用的速度较慢。相反,您应该尝试使用.join().

def encrypt(text, key): # Function that takes in two inputs: Text and key, which is the number of characters to shift forward
    output, text = [], str(text)
    limit = len(characters)
    while key > limit:
        key -= limit # This is my attempt to simplify the key
    for i in text:
        if i in characters:
            output.append(characters[characters.index(i)+key]) # If i is in characters, the rotated character is concatenated to the output
        else:
            output.append(i) # Otherwise, it directly adds the text
    return output.join()

现在你的键优化基本上只是一个模运算,所以让我们用 `key = key % len(characters) 替换它。

def encrypt(text:str, key:int): # Function that takes in two inputs: Text and key, which is the number of characters to shift forward
    output, text = [], str(text)
    key = key % len(characters)
    for i in text:
        if i in characters:
            output.append(characters[characters.index(i)+key]) # If i is in characters, the rotated character is concatenated to the output
        else:
            output.append(i) # Otherwise, it directly adds the text
    return output.join()

现在是您的查找方法。它希望O(n)复杂,并且具有O(nm)复杂性。考虑到您可能对大文本进行加密,您可能希望交换一些空间以节省时间。让我们改用映射结构。

然后添加一些收尾工作,使这个更漂亮。

def encrypt(text:str, key:int, characters:str=characters): 
    '''
    Function that shifts input by the number of buckets specified in key.
    Unknown characters are retained.

    :param text: text to be encrypted
    :param key: number to shift by
    :param characters: string specifying character ordering, None for default.

    :return: encrypted string
    '''
    if not isinstance(text, str) or not isinstance(key, int):
        raise ValueError('Incorrect param type')

    output= []
    l = len(characters)
    key = key % l
    char_map = { characters[i]:((i+key) % l) for i in characters}
    for i in text:
        ch = char_map.get(i)
        if ch is None:
            ch = i
        output.append(ch)
    return output.join()

推荐阅读