gpt4 book ai didi

python - ROT(n) 编码器和解码器,但解码器不工作

转载 作者:行者123 更新时间:2023-12-01 00:43:37 30 4
gpt4 key购买 nike

我知道有很多方法可以编写 ROT(n) 函数。但我不想有一些带有字符的表。

所以,我尝试编写一个带有解码器的简单 ROT(n),作为练习项目。编码功能工作正常。但解码器不断将“a”更改为“z”。

有人可以向我解释一下我做错了什么吗?

下面的 (Python3) 代码将所有内容更改为小写,忽略任何特殊字符。

import random
import string

shift = random.randint(1, 20)


# Encoder:
def encode(string):
coded_string = []
string = string.lower()
for c in string:
if ord(c) >= 97 and ord(c) <= 122:
c = (ord(c) + shift) % 122
if c <= 97:
c += 97
coded_string.append(chr(c))
continue
coded_string.append(c)
return ''.join(coded_string)


# Decoder:
def decode(string):
decoded_string = []
for c in string:
if ord(c) >= 97 and ord(c) <= 122:
if ord(c) - shift <= 97:
c = (ord(c) % 97) + (122 - shift)
decoded_string.append(chr(c))
continue
c = ord(c) - shift
decoded_string.append(chr(c))
continue
decoded_string.append(c)
return ''.join(decoded_string)


# Test Function:
def tryout(text):
test = decode(encode(text))
try:
assert test == text, 'Iznogoedh!'
except AssertionError as AE:
print(AE, '\t', test)
else:
print('Yes, good:', '\t', test)


# Random text generator:
def genRandomWord(n):
random_word = ''
for i in range(n):
random_word += random.choice(string.ascii_lowercase)
return random_word


# Some tests:
print(f'Shift: {shift}')
tryout('pokemon')
tryout("chip 'n dale rescue rangers")
tryout('Ziggy the Vulture or Zurg')
tryout('Fine # (*day%, to* code@ in Pyth0n3!')
tryout(genRandomWord(10))
tryout(genRandomWord(20))

示例输出:

Shift: 7
Yes, good: pokemon
Iznogoedh! chip 'n dzle rescue rzngers
Iznogoedh! ziggy the vulture or zurg
Iznogoedh! fine # (*dzy%, to* code@ in pyth0n3!
Yes, good: qrwmfyogjg
Yes, good: ihrcuvzyznlvghrtnuno

但是,忽略随机字符串测试,我期望:

Shift: 7
Yes, good: pokemon
Yes, good: chip 'n dale rescue rangers
Yes, good: ziggy the vulture or zurg
Yes, good: fine # (*day%, to* code@ in pyth0n3!

最佳答案

首先,您的tryout()测试函数忘记将输入小写,因此对于实际通过的 Ziggy 示例来说,它失败了;修正后的测试是:

# Test Function:
def tryout(text):
test = decode(encode(text))
try:
assert test == text.lower(), 'Iznogoedh!'
except AssertionError as AE:
print(AE, '\t', test)
else:
print('Yes, good:', '\t', test)

错误出现在您的解码函数中;对于 7 的移位,您可以看到 a 的编码字母-> h无法正确映射回来,而 i (来自 b ),确实有效:

>>> decode('h')
'z'
>>> decode('i')
'b'

然而,错误更进一步;前 7 个字母均被误译; g映射到y , f映射到x等。如果您使用较低的类次,则很容易看到:

>>> for encoded in 'abcd': print(decode(encoded), end=' ')
... else: print()
...
w x y z

那些应该已映射回x , y , za 。所以这是一个相差一错误,它在您的测试中:

if ord(c) - shift <= 97:

何时 shift是 3,并且 cd , ord(c) - shift等于 97,不应调整。更改<=< :

if ord(c) - shift < 97:

所以固定decode()函数则变为:

def decode(string):
decoded_string = []
for c in string:
if ord(c) >= 97 and ord(c) <= 122:
if ord(c) - shift < 97:
c = (ord(c) % 97) + (122 - shift)
decoded_string.append(chr(c))
continue
c = ord(c) - shift
decoded_string.append(chr(c))
continue
decoded_string.append(c)
return ''.join(decoded_string)

您可能想了解%此处的取模运算符,可以帮助“环绕”值以适应某个范围,例如字母 a 的值范围通过z .

如果采用 ASCII 代码点,减去 97,然后使用调整后的值(减或加移位,具体取决于编码或解码),然后用 % 26 包装结果值,您总是会出现在“另一边”,并且可以将结果加回到 97:

>>> ord('a') - 97   # a is the 'zeroth' letter in the alphabet, z is the 25th
0
>>> ord('a') - 97 - shift # shifted by 3 puts it outside the 0 - 25 range
-3
>>> (ord('a') - 97 - shift) % 26 # modulo 26 puts it back in the range, from the end
23
>>> chr((ord('a') - 97 - shift) % 26 + 97) # add 97 back on to go back to the decoded letter
'x'

另一个“技巧”是使用 bytes object ,将您的输入编码为 UTF-8。 bytes对象是整数序列,已由ord()处理。函数,可以这么说。只需循环并将移位应用于正确范围内的字节,并将这些整数附加到列表中。然后您可以创建一个新的 bytes列表中的对象并解码回字符串:

def shift_by_n(n, value):
as_bytes = value.lower().encode('utf8')
encoded = []
for v in as_bytes:
if 97 <= v <= 122:
v = ((v - 97 + n) % 26) + 97
encoded.append(v)
return bytes(encoded).decode('utf8')

上述函数可以同时用于编码解码,只需将移位作为正值或负值传递即可:

def encode(string):
return shift_by_n(shift, string)

def decode(string):
return shift_by_n(-shift, string)

最后,您可以使用 str.translate() function,而不是测试每个字母。给定一个翻译表,它可以为您进行所有替换。您可以使用 str.maketrans() static method 轻松构建 ROT(n) 转换表。 。编码只是将字母表映射到相同的字母表,但带有 shift从开头开始的字符被删除并添加到结尾:

alphabet = 'abcdefghijklmnopqrstuvwxyz'

def encode(string):
# take all letters except the first 'shift' characters, and
# add those letters to the end instead
rotated = alphabet[shift:] + alphabet[:shift]
translate_map = str.maketrans(alphabet, rotated)
return string.lower().translate(translate_map)

解码使用相同的rotated字符串,但 str.maketrans() 的参数顺序已交换:

def decode(string):
# take all letters except the first 'shift' characters, and
# add those letters to the end instead
rotated = alphabet[shift:] + alphabet[:shift]
translate_map = str.maketrans(rotated, alphabet)
return string.translate(translate_map)

使上述函数也适用于大写字母,只需要连接 alphabet.upper()rotated.upper()结果为alphabetrotated ,分别调用 str.maketrans() 时(并删除 .lower() 中的 encode() 调用)。我将把它留给读者来实现。

关于python - ROT(n) 编码器和解码器,但解码器不工作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57163173/

30 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com