[英]How can I solve this Caesar-cipher style encrypting in python 2.7.13?
[英]How can I solve a problem with caesar code in Python
我正在嘗試創建一個簡單的 Caesar Code 函數,該函數必須解密輸入中給出的字符串。
明文 = ABCDEFGHIJKLMNOPQRSTU VWXYZ
加密 = DEFGHIJKLMNOPQRSTUVWX YZABC
這是我的 DECIPHER 代碼:
def deciph(s):
b='abcdefghijklmnopqrstuvwxyz'
a='defghijklmnopqrstuvwxyzabc'
for i in s:
for j in range(len(a)):
if i==a[j]:
s=s.replace(i,b[j])
return s
這段代碼幾乎總是可以正常工作,例如:
deciph('vxq') --> 'sun'
deciph('ohwwhu') --> 'letter'
這個案例的問題是:
deciph('sp')--> 'mm' #should be 'pm'
deciph('ol')-->'ii' #should be 'li'
因此,當第一個字母被解密時,就等於第二個字母被加密。
如何修改我的代碼? 錯誤在哪里? 我知道在互聯網上有很多其他方法可以做同樣的練習,但現在我有興趣了解我的代碼的錯誤。
讓我們使用您的deciph('sp')
示例。 問題是當你做s=s.replace(i,b[j])
,你最初用'p'
替換's'
所有實例,給你s = 'pp'
,然后在第二遍,用'm'
替換'p'
所有實例,給你s = 'mm'
。 這可以通過保存一個新的初始變量rv = ''
,然后對每個字母使用rv+=b[j]
而不是改變s
來糾正。 然后最后,只需返回rv
。
如前所述,您觀察到的問題是由於無條件地將s
的每個字符替換為“清除”字符 - 因為a
和b
由相同的字母組成,並且str.replace(x, y)
將所有出現的x
替換為y
,一些字符被一次又一次地“破譯”......
正確解決方案的第一步是手動構建一個新字符串,而不是使用str.replace
:
def decipher(s):
result = []
for char in s:
for index, crypted in enumerate(a):
if char == crypted:
result.append(b[index])
# no need to go further
break
else:
# The else clause of a for loop is only executed
# if the for loop runs to the end without being
# interrupted by a break statement.
#
# Here we use it to handle the case of whitespaces
# or any other char that's in `s` but not in `a`
result.append(c)
return "".join(result)
現在雖然這會產生預期的結果,但它非常復雜且效率低下。 您所做的基本上是映射- 在這種情況下,將加密字符映射到解密字符 - 所以這里顯而易見的解決方案是使用Python 的主要mapping
內置類型: dict
:
CLEAR = 'abcdefghijklmnopqrstuvwxyz'
CRYPT = 'defghijklmnopqrstuvwxyzabc'
DECIPHER_MAP = dict(zip(CRYPT, CLEAR))
def decipher(s):
## the 'unrolled' version:
# result = []
# for c in s:
# result.append(DECIPHER_MAP.get(c, c))
# return "".join(result)
# which is even simpler _and_ faster (and uses less memory)
# using a generator expression.
return "".join(DECIPHER_MAP.get(c, c) for c in s)
如您所見,該算法要簡單得多。 它也更快(字典查找是 0(1) 並且高度優化),並且占用更少的內存(中間result
列表不需要)。
在編程中,選擇合適的數據結構是關鍵...
注意:
現在我有興趣了解我的代碼的錯誤。
這是非常值得稱贊的,至少可以說 - 我希望這里的每個人都會這樣做。 現在,您可以使用最簡單和基本的調試技術自己解決一些問題:通過在戰略時刻打印出您的當前狀態來跟蹤代碼執行:
def deciph(s):
for i in s:
print("i : '{}' - s : '{}'".format(i, s))
for j in range(len(a)):
if i==a[j]:
print("i == '{}' - replacing with '{}'".format(i, b[j]))
s = s.replace(i, b[j])
print("now s : '{}'".format(s))
return s
>>> deciph("pme")
i : 'p' - s : 'pme'
i == 'p' - replacing with 'm'
now s : 'mme'
i : 'm' - s : 'mme'
i == 'm' - replacing with 'j'
now s : 'jje'
i : 'e' - s : 'jje'
i == 'e' - replacing with 'b'
now s : 'jjb'
'jjb'
您可以使用find()
方法來查找循環中字符的位置。
def deciph(s):
b='abcdefghijklmnopqrstuvwxyz'
a='defghijklmnopqrstuvwxyzabc'
decrypted = ''
for i in s:
pos = a.find(i)
if pos != -1:
decrypted += b[pos]
else:
pass # Here you can throw an error
# Or you can directly pass it to the decrypted string
# since you want spaces and other punctuation to remain
# decrypted += i
return decrypted
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.