以下函数 rot(s, n) 使用 ROT-n 编码对字符串 s 进行任何整数 n 编码,n 默认为 13。支持大写和小写字母。 n 的值超过26 或负值时要适当处理,例如移位27 个位置等于移位1 个位置。解码是通过invrot(s, n)完成的。
import string
def rot(s, n=13):
'''Encode string s with ROT-n, i.e., by shifting all letters n positions.
When n is not supplied, ROT-13 encoding is assumed.
'''
upper = string.ascii_uppercase
lower = string.ascii_lowercase
upper_start = ord(upper[0])
lower_start = ord(lower[0])
out = ''
for letter in s:
if letter in upper:
out += chr(upper_start + (ord(letter) - upper_start + n) % 26)
elif letter in lower:
out += chr(lower_start + (ord(letter) - lower_start + n) % 26)
else:
out += letter
return(out)
def invrot(s, n=13):
'''Decode a string s encoded with ROT-n-encoding
When n is not supplied, ROT-13 is assumed.
'''
return(rot(s, -n))
The following function rot(s, n) encodes a string s with ROT-n encoding for any integer n, with n defaulting to 13. Both upper- and lowercase letters are supported. Values of n over 26 or negative values are handled appropriately, e.g., shifting by 27 positions is equal to shifting by one position. Decoding is done with invrot(s, n).
import string
def rot(s, n=13):
'''Encode string s with ROT-n, i.e., by shifting all letters n positions.
When n is not supplied, ROT-13 encoding is assumed.
'''
upper = string.ascii_uppercase
lower = string.ascii_lowercase
upper_start = ord(upper[0])
lower_start = ord(lower[0])
out = ''
for letter in s:
if letter in upper:
out += chr(upper_start + (ord(letter) - upper_start + n) % 26)
elif letter in lower:
out += chr(lower_start + (ord(letter) - lower_start + n) % 26)
else:
out += letter
return(out)
def invrot(s, n=13):
'''Decode a string s encoded with ROT-n-encoding
When n is not supplied, ROT-13 is assumed.
'''
return(rot(s, -n))
def rot13(s):
rot=lambda x:chr(ord(x)+13) if chr(ord(x.lower())+13).isalpha()==True else chr(ord(x)-13)
s=[rot(i) for i in filter(lambda x:x!=',',map(str,s))]
return ''.join(s)
This works for uppercase and lowercase. I don't know how elegant you deem it to be.
def rot13(s):
rot=lambda x:chr(ord(x)+13) if chr(ord(x.lower())+13).isalpha()==True else chr(ord(x)-13)
s=[rot(i) for i in filter(lambda x:x!=',',map(str,s))]
return ''.join(s)
def rot13(s):
chars = "AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz"
trans = chars[26:]+chars[:26]
rot_char = lambda c: trans[chars.find(c)] if chars.find(c) > -1 else c
return ''.join(rot_char(c) for c in s)
输出(使用 python 2.7 测试):
print rot13("Hello World!") --> Uryyb Jbeyq!
You can support uppercase letters on the original code posted by Mr. Walter by alternating the upper case and lower case letters.
If you notice the index of the uppercase letters are all even numbers while the index of the lower case letters are odd.
A = 0 a = 1,
B = 2, b = 3,
C = 4, c = 4,
...
This odd-even pattern allows us to safely add the amount needed without having to worry about the case.
trans = chars[26:] + chars[:26]
The reason you add 26 is because the string has doubled in letters due to the upper case letters. However, the shift is still 13 spaces on the alphabet.
The full code:
def rot13(s):
chars = "AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz"
trans = chars[26:]+chars[:26]
rot_char = lambda c: trans[chars.find(c)] if chars.find(c) > -1 else c
return ''.join(rot_char(c) for c in s)
def rot13(s):
return ''.join([chr(ord(n) + (13 if 'Z' < n < 'n' or n < 'N' else -13)) if n.isalpha() else n for n in s])
def rot13_verbose(s):
x = []
for n in s:
if n.isalpha():
# 'n' is the 14th character in the alphabet so if a character is bigger we can subtract 13 to get rot13
ort = 13 if 'Z' < n < 'n' or n < 'N' else -13
x.append(chr(ord(n) + ort))
else:
x.append(n)
return ''.join(x)
# crazy .min version (99 characters) disclaimer: not pep8 compatible^
def r(s):return''.join([chr(ord(n)+(13if'Z'<n<'n'or'N'>n else-13))if n.isalpha()else n for n in s])
Interesting exercise ;-) i think i have the best solution because:
no modules needed, uses only built-in functions --> no deprecation
it can be used as a one liner
based on ascii, no mapping dicts/strings etc.
Python 2 & 3 (probably Python 1):
def rot13(s):
return ''.join([chr(ord(n) + (13 if 'Z' < n < 'n' or n < 'N' else -13)) if n.isalpha() else n for n in s])
def rot13_verbose(s):
x = []
for n in s:
if n.isalpha():
# 'n' is the 14th character in the alphabet so if a character is bigger we can subtract 13 to get rot13
ort = 13 if 'Z' < n < 'n' or n < 'N' else -13
x.append(chr(ord(n) + ort))
else:
x.append(n)
return ''.join(x)
# crazy .min version (99 characters) disclaimer: not pep8 compatible^
def r(s):return''.join([chr(ord(n)+(13if'Z'<n<'n'or'N'>n else-13))if n.isalpha()else n for n in s])
def rot13(s):
lower_chars = ''.join(chr(c) for c in range (97,123)) #ASCII a-z
upper_chars = ''.join(chr(c) for c in range (65,91)) #ASCII A-Z
lower_encode = lower_chars[13:] + lower_chars[:13] #shift 13 bytes
upper_encode = upper_chars[13:] + upper_chars[:13] #shift 13 bytes
output = "" #outputstring
for c in s:
if c in lower_chars:
output = output + lower_encode[lower_chars.find(c)]
elif c in upper_chars:
output = output + upper_encode[upper_chars.find(c)]
else:
output = output + c
return output
另一种解决方案是移位。也许这段代码可以帮助其他人更好地理解 rot13。 还没有完全测试过。
def rot13(s):
lower_chars = ''.join(chr(c) for c in range (97,123)) #ASCII a-z
upper_chars = ''.join(chr(c) for c in range (65,91)) #ASCII A-Z
lower_encode = lower_chars[13:] + lower_chars[:13] #shift 13 bytes
upper_encode = upper_chars[13:] + upper_chars[:13] #shift 13 bytes
output = "" #outputstring
for c in s:
if c in lower_chars:
output = output + lower_encode[lower_chars.find(c)]
elif c in upper_chars:
output = output + upper_encode[upper_chars.find(c)]
else:
output = output + c
return output
Another solution with shifting. Maybe this code helps other people to understand rot13 better. Haven't tested it completely.
def rot13(clear):
CLEAR = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'
ROT13 = 'NOPQRSTUVWXYZABCDEFGHIJKLMnopqrstuvwxyzabcdefghijklm'
TABLE = {x: y for x, y in zip(CLEAR, ROT13)}
for c in clear:
yield TABLE.get(c, c)
if __name__ == '__main__':
CLEAR = 'Hello, World!'
R13 = 'Uryyb, Jbeyq!'
r13 = ''.join(rot13(CLEAR))
assert r13 == R13
clear = ''.join(rot13(r13))
assert clear == CLEAR
I found this post when I started wondering about the easiest way to implement rot13 into Python myself. My goals were:
Works in both Python 2.7.6 and 3.3.
Handle both upper and lower case.
Not use any external libraries.
This meets all three of those requirements. That being said, I'm sure it's not winning any code golf competitions.
def rot13(string):
CLEAR = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'
ROT13 = 'NOPQRSTUVWXYZABCDEFGHIJKLMnopqrstuvwxyzabcdefghijklm'
TABLE = {x: y for x, y in zip(CLEAR, ROT13)}
return ''.join(map(lambda x: TABLE.get(x, x), string))
if __name__ == '__main__':
CLEAR = 'Hello, World!'
R13 = 'Uryyb, Jbeyq!'
r13 = rot13(CLEAR)
assert r13 == R13
clear = rot13(r13)
assert clear == CLEAR
This works by creating a lookup table and simply returning the original character for any character not found in the lookup table.
Update
I got to worrying about someone wanting to use this to encrypt an arbitrarily-large file (say, a few gigabytes of text). I don't know why they'd want to do this, but what if they did? So I rewrote it as a generator. Again, this has been tested in both Python 2.7.6 and 3.3.
def rot13(clear):
CLEAR = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'
ROT13 = 'NOPQRSTUVWXYZABCDEFGHIJKLMnopqrstuvwxyzabcdefghijklm'
TABLE = {x: y for x, y in zip(CLEAR, ROT13)}
for c in clear:
yield TABLE.get(c, c)
if __name__ == '__main__':
CLEAR = 'Hello, World!'
R13 = 'Uryyb, Jbeyq!'
r13 = ''.join(rot13(CLEAR))
assert r13 == R13
clear = ''.join(rot13(r13))
assert clear == CLEAR
def rot13(text):
return "".join([x if ord(x) not in range(65, 91)+range(97, 123) else
chr(((ord(x)-97+13)%26)+97) if x.islower() else
chr(((ord(x)-65+13)%26)+65) for x in text])
Short solution:
def rot13(text):
return "".join([x if ord(x) not in range(65, 91)+range(97, 123) else
chr(((ord(x)-97+13)%26)+97) if x.islower() else
chr(((ord(x)-65+13)%26)+65) for x in text])
发布评论
评论(20)
这很简单:
It's very simple:
maketrans()
/translate()
解决方案...Python 2.x
Python 3.x
maketrans()
/translate()
solutions…Python 2.x
Python 3.x
这适用于 Python 2(但不适用于 Python 3):
This works on Python 2 (but not Python 3):
maketrans
和translate
str 的方法
对于这种类型的事情很方便。这是一个通用的解决方案:
The
maketrans
andtranslate
methods ofstr
are handy for this type of thing.Here's a general solution:
从内置模块
this.py
(导入此
):From the builtin module
this.py
(import this
):从 Python 3.1 开始,
string.translate
和string.maketrans
不再存在。但是,这些方法可以与bytes
一起使用。因此,直接受 Paul Rubel 的解决方案启发的最新解决方案是:
从
string
到bytes
的转换,反之亦然,可以使用编码
和解码
内置函数。As of Python 3.1,
string.translate
andstring.maketrans
no longer exist. However, these methods can be used withbytes
instead.Thus, an up-to-date solution directly inspired from Paul Rubel's one, is:
Conversion from
string
tobytes
and vice-versa can be done with theencode
anddecode
built-in functions.试试这个:
Try this:
在 python-3 中,@amber 提到的
str
-codec 已移至codecs
标准库:In python-3 the
str
-codec that @amber mentioned has moved tocodecs
standard-library:以下函数
rot(s, n)
使用 ROT-n
编码对字符串s
进行任何整数n
编码,n
默认为 13。支持大写和小写字母。 n 的值超过26 或负值时要适当处理,例如移位27 个位置等于移位1 个位置。解码是通过invrot(s, n)
完成的。The following function
rot(s, n)
encodes a strings
with ROT-n
encoding for any integern
, withn
defaulting to 13. Both upper- and lowercase letters are supported. Values ofn
over 26 or negative values are handled appropriately, e.g., shifting by 27 positions is equal to shifting by one position. Decoding is done withinvrot(s, n)
.rot13 字符串
S
的单行代码:A one-liner to rot13 a string
S
:对于任意值,类似的方法适用于 2.x
For arbitrary values, something like this works for 2.x
这适用于大写和小写。我不知道你认为它有多优雅。
This works for uppercase and lowercase. I don't know how elegant you deem it to be.
您可以通过交替大小写字母来支持 Walter 先生发布的原始代码上的大写字母。
如果您注意到大写字母的索引都是偶数,而小写字母的索引是奇数。
这种奇偶模式使我们能够安全地添加所需的金额,而不必担心大小写。
添加 26 的原因是由于大写字母,字符串的字母数量增加了一倍。然而,字母表上的移位仍然是 13 个空格。
完整代码:
输出(使用 python 2.7 测试):
You can support uppercase letters on the original code posted by Mr. Walter by alternating the upper case and lower case letters.
If you notice the index of the uppercase letters are all even numbers while the index of the lower case letters are odd.
This odd-even pattern allows us to safely add the amount needed without having to worry about the case.
The reason you add 26 is because the string has doubled in letters due to the upper case letters. However, the shift is still 13 spaces on the alphabet.
The full code:
OUTPUT (Tested with python 2.7):
有趣的练习;-) 我认为我有最好的解决方案,因为:
2 和 Python 2 3(可能是Python 1):
Interesting exercise ;-) i think i have the best solution because:
Python 2 & 3 (probably Python 1):
另一种解决方案是移位。也许这段代码可以帮助其他人更好地理解 rot13。
还没有完全测试过。
Another solution with shifting. Maybe this code helps other people to understand rot13 better.
Haven't tested it completely.
当我开始想知道最简单的实现方法时,我发现了这篇文章
我自己将 rot13 导入到 Python 中。我的目标是:
这满足了所有这三个要求。话虽如此,我确信它不会赢得任何代码高尔夫比赛。
这是通过创建一个查找表并简单地返回查找表中未找到的任何字符的原始字符来实现的。
更新
我担心有人想用它来加密任意大的文件(例如,几千兆字节的文本)。我不知道他们为什么要这么做,但如果他们这么做了怎么办?所以我将其重写为生成器。同样,这已经在 Python 2.7.6 和 3.3 中进行了测试。
I found this post when I started wondering about the easiest way to implement
rot13
into Python myself. My goals were:This meets all three of those requirements. That being said, I'm sure it's not winning any code golf competitions.
This works by creating a lookup table and simply returning the original character for any character not found in the lookup table.
Update
I got to worrying about someone wanting to use this to encrypt an arbitrarily-large file (say, a few gigabytes of text). I don't know why they'd want to do this, but what if they did? So I rewrote it as a generator. Again, this has been tested in both Python 2.7.6 and 3.3.
如果没有使用模运算符的单个语句,我就无法将这个问题留在这里。
这不是Pythonic,也不是好的实践,但它确实有效!
I couldn't leave this question here with out a single statement using the modulo operator.
This is not pythonic nor good practice, but it works!
你也可以使用这个
You can also use this also
简短的解决方案:
Short solution: