我正在尝试撤销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'
答案 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.')