用字典反向字符串翻译

时间:2017-06-23 15:46:30

标签: python dictionary

我正在尝试撤销translate功能的使用。我将字典传递给str.maketrans,根据字典正确翻译原始字符串。

cipher_dictionary = {'a': 'h5c', 'b': 'km3', 'c': '5fv'}

def cipher(text):
    trans = str.maketrans(cipher_dictionary)
    return text.translate(trans)

上面是示例字典,以及我用来翻译字符串的函数。翻译abc会给我h5ckm35fv,这是理想的。

现在,要反转它,我正在尝试使用以下功能。

def decipher(text):
    reverse = {value: key for key, value in cipher_dictionary.items()}
    trans = str.maketrans(reverse)
    return text.translate(trans)

使用它会引发错误。

Traceback (most recent call last):
  File "C:\Users\lukas\Desktop\cipher.py", line 21, in <module>
    deciphered = decipher(ciphered)
  File "C:\Users\lukas\Desktop\cipher.py", line 13, in decipher
    trans = str.maketrans(reverse)
ValueError: string keys in translate table must be of length 1

我知道这是因为cipher_dictionary中的值与a,b和c的长度不等。如何重写decipher函数,将h5ckm35fv翻译回abc

cipher_dictionary = {'a': 'h5c', 'b': 'km3', 'c': '5fv'}


def cipher(text):
    trans = str.maketrans(cipher_dictionary)
    return text.translate(trans)


def decipher(text):
    reverse = {value: key for key, value in cipher_dictionary.items()}
    trans = str.maketrans(reverse)
    return text.translate(trans)

if __name__ == '__main__':
    text_to_cipher = 'abc'
    ciphered = cipher(text_to_cipher)
    print(ciphered)

    deciphered = decipher(ciphered)
    print(deciphered)

运行答案中提供的任何功能都非常有效,除非输入中有空白区域。

Text to cipher: some white space
Ciphered text: px3h54oa4b83 ky6u1v0t6yq3b83 px3sy9h5c5fvb83
Traceback (most recent call last):
  File "C:\Users\Lukasz\Desktop\Python\Cipher\cip.py", line 45, in <module>
    deciphered = decipher(ciphered)
  File "C:\Users\Lukasz\Desktop\Python\Cipher\cip.py", line 36, in decipher
    decoded_text = ''.join(reverse[text[i:i+3]] for i in range(0, len(text), 3))
  File "C:\Users\Lukasz\Desktop\Python\Cipher\cip.py", line 36, in <genexpr>
    decoded_text = ''.join(reverse[text[i:i+3]] for i in range(0, len(text), 3))
KeyError: ' ky'

3 个答案:

答案 0 :(得分:1)

def decipher(sentence):
    reverse = {value: key for key, value in cipher_dictionary.items()}
    decoded_text = ' '.join(''.join(reverse[word[i:i+3]] for i in range(0, len(word), 3)) for word in sentence.split(' '))
    return decoded_text

假设每个字母都被编码成一组3个字母。

答案 1 :(得分:1)

如果您知道所有密码值的长度为3(即cipher_dictionary中的所有值都是三个字符长),那么:

def decrypt(ciphertext, cipher_dict):
    decipher_dict = {v:k for k,v in cipher_dict.items()}
    answer = []
    for cipher in (ciphertext[i:i+3] for i in range(0,len(ciphertext), 3)):
        answer.append(decipher_dict[cipher])

    return ''.join(answer)

另一方面,如果你不知道所有的值都是长度为3(或者它们的大小不一致),那么试试这个:

def decrypt(ciphertext, cipher_dict):
    decipher_dict = {v:k for k,v in cipher_dict.items()}
    answer = []
    start = 0
    for end in range(len(ciphertext)):
        if ciphertext[start:end] not in decipher_dict: continue
        answer.append(decipher_dict[ciphertext[start:end]])
        start = end

return ''.join(answer)

这个问题是它是一个贪婪的算法,并且带来了naïvité的所有缺点

<强>更新

如果你想用句子(用空格分隔的单词)来做这个:

encryptedSentence = '...'
answer = []
for word in sentence.split():
    answer.append(decrypt(word, cipher_dict))

return ' '.join(answer)

答案 2 :(得分:1)

假设字典中的值为前缀免费代码,那么您可以继续尝试未处理密文的前缀,直到在反向字典中找到匹配项:

def decipher(text, d):
r = {v: k for k,v in d.items()} # Reversed dictionary
plaintext = ''
index = 0
length = 1
while index + length <= len(text):
    try:
        plaintext += r[text[index:index+length]]
        index = index + length
        length = 1
    except:
        length += 1
return plaintext

如果字典的值不形成前缀自由代码,则算法涉及回溯,如果密码是非双射的,则返回一个可能的明文:

def decipher2(text, d):
r = {v: k for k,v in d.items()} # Reversed dictionary
length = 1
while length <= len(text):
    try:
        val = r[text[:length]]
        if length == len(text):
            return val
        else:
            return val + decipher2(text[length:], d)
    except:
        length += 1
raise ValueError('Malformed input.')