gpt4 book ai didi

ruby - Ruby 中需要带有字母数字的唯一随机字符串

转载 作者:行者123 更新时间:2023-12-04 14:38:25 25 4
gpt4 key购买 nike

我正在使用以下代码生成唯一的 10 个字符的随机字符串 [A-Z a-z 0-9]在 ruby 中:

random_code = [*('a'..'z'),*('0'..'9'),*('A'..'Z')].shuffle[0, 10].join

但是,有时这个随机字符串不包含数字或大写字符。你能帮我有一种方法来生成一个唯一的随机字符串,该字符串至少需要一个数字、一个大写和一个小写字符吗?

最佳答案

down   = ('a'..'z').to_a
up = ('A'..'Z').to_a
digits = ('0'..'9').to_a
all = down + up + digits
[down.sample, up.sample, digits.sample].
concat(7.times.map { all.sample }).
shuffle.
join
#=> "TioS8TYw0F"

[编辑:以上反射(reflect)了对问题的误解。不过,我会离开它。不让字符出现多次:
def rnd_str
down = ('a'..'z').to_a
up = ('A'..'Z').to_a
digits = ('0'..'9').to_a
[extract1(down), extract1(up), extract1(digits)].
concat(((down+up+digits).sample(7))).shuffle.join
end

def extract1(arr)
i = arr.size.times.to_a.sample
c = arr[i]
arr.delete_at(i)
c
end

rnd_str #=> "YTLe0WGoa1"
rnd_str #=> "NrBmAnE9bT"
down.sample.shift (等)会比 extract1 更紧凑,但效率低下实在令人难以忍受。

如果您不想重复随机字符串,只需保留您生成的字符串列表。如果生成列表中的另一个,则丢弃它并生成另一个。但是,您不太可能需要生成任何额外的内容。例如,如果您生成 100 个随机字符串(满足至少一个小写字母、大写字母和数字的要求),则出现一个或多个重复字符串的几率约为 700,000 分之一:
t = 107_518_933_731
n = t+1
t = t.to_f
(1.0 - 100.times.reduce(1.0) { |prod,_| prod * (n -= 1)/t }).round(10)
#=> 1.39e-07

哪里 t = C(62,10)C(62,10)定义如下。

另一种选择

有一种非常简单的方法可以做到这一点,结果证明是非常有效的:只采样而不替换,直到找到满足至少小写字母、一个大写字母和一个数字的要求的样本。我们可以这样做:
DOWN   = ('a'..'z').to_a
UP = ('A'..'Z').to_a
DIGITS = ('0'..'9').to_a
ALL = DOWN + UP + DIGITS

def rnd_str
loop do
arr = ALL.sample(10)
break arr.shuffle.join unless (DOWN&&arr).empty? || (UP&&arr).empty? ||
(DIGITS&&arr).empty?
end
end

rnd_str #=> "3jRkHcP7Ge"
rnd_str #=> "B0s81x4Jto

在找到“好的”样本之前,我们平均必须剔除多少样本?事实证明(如果您真的非常感兴趣,请参见下文)获得“坏”字符串的概率(即,从 all 的 62 个元素中随机选择 10 个字符,没有替换,没有小写字母,没有大写字母或没有数字,只有大约 0.15. (15%). 这意味着在找到一个好的样本之前,85% 的时间没有坏样本会被拒绝。

事实证明,在采样一个好的字符串之前,将被采样的坏字符串的预期数量是:
0.15/0.85 =~ 0.17

下面显示了上述概率是如何得出的,如果有人感兴趣的话。

n_down是可以抽取 10 个没有小写字母的样本的方法数:
n_down = C(36,10) = 36!/(10!*(36-10)!)

其中(二项式系数) C(36,10)等于一次可以“拿走”10个的36个“东西”的组合数,等于:
C(36,10) = 36!/(10!*(36-10)!) #=> 254_186_856

相似地,
n_up = n_down #=> 254_186_856


n_digits = C(52,10) #=> 15_820_024_220

我们可以将这三个数字相加得到:
n_down + n_up + n_digits #=> 16_328_397_932

这几乎是(但不完全是)绘制 10 个字符的方法数,无需替换,不包含小写字母字符、大写字母或数字。 “不完全”,因为有一些重复计算。必要的调整如下:
n_down + n_up + n_digits - 2*C(26,10) - 3
#=> 16_317_774_459

为了获得从 62 人中抽取 10 个样本的概率,没有替换,没有小写字母,没有大写字母或没有数字,我们用这个数字除以从 62 个没有替换的情况下可以抽取 10 个字符的方式总数替代品:
(16_317_774_459.0/c(62,10)).round(2)
#=> 0.15

关于ruby - Ruby 中需要带有字母数字的唯一随机字符串,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31848723/

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