栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 面试经验 > 面试问答

生成带有较低拉丁字母的大随机字符串的最快方法

面试问答 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

生成带有较低拉丁字母的大随机字符串的最快方法

这是Python
3代码,可在

0.28
几秒钟内生成1000000个“随机”小写字母(另请参阅
0.11
-seconds解决方案;问题中的@Ashwini
Chaudhary的代码
0.55
在我的计算机上需要几秒钟,@ Markku K.的代码-
0.53
):

#!/usr/bin/env python3import osimport sysdef write_random_lowercase(n):    min_lc = ord(b'a')    len_lc = 26    ba = bytearray(os.urandom(n))    for i, b in enumerate(ba):        ba[i] = min_lc + b % len_lc # convert 0..255 to 97..122    sys.stdout.buffer.write(ba)write_random_lowercase(1000000)

% len_lc
尽管它仍然满足条件(ascii,小写字母,1、2、3个字母序列的频率),但使分布偏斜(请参阅最后的解决方法):

$ python3 generate-random.py | python3 check-seq.py

在哪里

check-seq.py

#!/usr/bin/env python3import sysfrom collections import Counterfrom string import ascii_lowercasedef main():    limits = [40000, 2000, 100]    s = sys.stdin.buffer.readline() # a single line    assert 1000000 <= len(s) <= 1000002 # check length +/- newline    s.depre('ascii','strict') # check ascii    assert set(s) == set(ascii_lowercase.enpre('ascii')) # check lowercase    for n, lim in enumerate(limits, start=1):        freq = Counter(tuple(s[i:i+n]) for i in range(len(s)))        assert max(freq.values()) <= lim, freqmain()

注意:在acm.timus.ru上

generate-random.py
给出“超出输出限制”。

为了提高性能,您可以使用

bytes.translate()
方法(
0.11
秒):

#!/usr/bin/env python3import osimport sys# make translation table from 0..255 to 97..122tbl = bytes.maketrans(bytearray(range(256)),bytearray([ord(b'a') + b % 26 for b in range(256)]))# generate random bytes and translate them to lowercase asciisys.stdout.buffer.write(os.urandom(1000000).translate(tbl))

如何解决
% len_lc
偏斜

256
(字节数)不能被
26
(低拉丁字母数)均分,因此该公式
min_lc + b % len_lc
使某些值出现的频率比其他值少,例如:

#!/usr/bin/env python3"""Find out skew: x = 97 + y % 26 where y is uniform from [0, 256) range."""from collections import Counter, defaultdictdef find_skew(random_bytes):    char2freq = Counter(chr(ord(b'a') + b % 26) for b in random_bytes)    freq2char = defaultdict(set)    for char, freq in char2freq.items():        freq2char[freq].add(char)    return {f: ''.join(sorted(c)) for f, c in freq2char.items()}print(find_skew(range(256)))# -> {9: 'wxyz', 10: 'abcdefghijklmnopqrstuv'}

这里,输入

range(256)
是均匀分布的(每个字节正好一次出现),但
'wxyz'
在输出信往往小于其余部分
9
10
发生。要解决此问题,可以丢弃未对齐的字节:

print(find_skew(range(256 - (256 % 26))))# -> {9: 'abcdefghijklmnopqrstuvwxyz'}

在此,输入是均匀分布的字节,

[0, 234)
输出范围是均匀分布的ascii小写字母。

bytes.translate()
接受第二个参数来指定要删除的字节:

#!/usr/bin/env python3import osimport sysnbytes = 256nletters = 26naligned = nbytes - (nbytes % nletters)tbl = bytes.maketrans(bytearray(range(naligned)),bytearray([ord(b'a') + b % nlettersfor b in range(naligned)]))bytes2delete = bytearray(range(naligned, nbytes))R = lambda n: os.urandom(n).translate(tbl, bytes2delete)def write_random_ascii_lowercase_letters(write, n):    """*write* *n* random ascii lowercase letters."""        while n > 0:        # R(n) expected to drop `(nbytes - nletters) / nbytes` bytes        # to compensate, increase the initial size     n -= write(memoryview(R(n * nbytes // naligned + 1))[:n])write = sys.stdout.buffer.writewrite_random_ascii_lowercase_letters(write, 1000000)

如果随机生成器(

os.urandom
此处)产生的长字节序列超出了对齐范围(
>=234
),则
while
循环可能执行多次。

如果

random.getrandbits(8*n).to_bytes(n,'big')
使用代替,则时间性能可以提高另一个数量级
os.urandom(n)
。前者使用Mersenne
Twister作为核心生成器,它可能比
os.urandom()
使用操作系统提供的源更快。如果将随机字符串用于机密,则后者更为安全。



转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/624542.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号