我的任務是生成具有以下引數的隨機字串:
- 至少一個大寫字母
- 至少低一個
- 至少一位數
- 不允許重復的字符/數字(例如,不允許使用 aa,允許使用 aba,允許使用 Aa)
我能夠生成帶有 1,2,3 引數的隨機字串,但缺少引數 4 邏輯。
inputChars = [('a'..'z'), ('A'..'Z'),(0..9)].map(&:to_a).flatten
string = (0...16).map { inputChars[rand(inputChars.length)] }.join
uj5u.com熱心網友回復:
require 'set'
inputChars = [('a'..'z'), ('A'..'Z'),(0..9)].map(&:to_a).flatten
set_string = Set.new
loop do
break if set_string.size == 16
cr = inputChars[rand(inputChars.length)]
set_string << cr
end
output = set_string.to_a.join
我只是將您的地圖操作更改為回圈操作并添加 Set 資料結構以存盤來自隨機 inputChars 操作的字符。使用 Set 將不允許相同的字符
uj5u.com熱心網友回復:
讓我們從定義兩個常量開始。
CHARS_BY_TYPE = {
lower: ('a'..'z').to_a.freeze,
upper: ('A'..'Z').to_a.freeze,
digit: ('0'..'9').to_a.freeze
}.freeze
ALL = (CHARS_BY_TYPE[:lower] CHARS_BY_TYPE[:upper] CHARS_BY_TYPE[:digit]).freeze
#=> [["a", "b",..., "z", "A", "B",..., "Z", "0", "1",..., "9"]
我最初將通過從陣列中一次隨機選擇一個字符來構建一個指定長度的字串ALL,確保沒有兩個連續的字符是相同的。但是,不能保證生成的字串至少包含一個大寫字母、一個小寫字母和一個數字。
def append_random_char(last_char)
loop do
ch = ALL.sample
break ch unless ch == last_char
end
end
我們的主要方法將如下開始:
def random_string(str_len)
raise ArgumentError if str_len < 3
(str_len - 2).times.with_object('') { |_,s| s << append_random_char(s[-1]) }
# ...
end
例如:
s = random_string(40)
#=> "arN64kDw6ClzcNMj8WAkj1NJC2B5oFoRlcXl5S"
str_len是所需的字串長度,40在示例中。觀察s包含38沒有兩個連續字符相等的字符。稍后我們將需要添加2字符。例如,如果字串不包含數字,則添加的這兩個字符中的至少一個(在隨機位置)將是(隨機選擇的)數字。如果字串更短并且僅包含數字,例如,添加的兩個字符將是一個大寫字母和一個小寫字母。
接下來我們需要查看字串是否缺少大寫字母、小寫字母和/或數字。(不能缺少所有三個,因為字串必須包含至少三個字符。)
require 'set'
def types_to_add(str)
[:lower, :upper, :digit].select do |type|
st = CHARS_BY_TYPE[type].to_set
str.each_char.none? { |ch| st.include?(ch) }
end
end
對于上面生成的隨機字串,我們得到:
types_to_add(s)
#=> []
meaning that the string contains at least one uppercase letter, one lowercase letter and one digit. Try this:
types_to_add(s.gsub(/\d|[A-Z]/, '')
#=> [:upper, :digit]
See Enumerable#none?. CHARS_BY_TYPE[type] is converted to a set merely to speed look-ups.
Suppose now we need to insert an uppercase letter, lowercase letter or digit to satisfy the requirement that there is at least one of each in the string. Specifically, we wish to insert a randomly-drawn character (from CHARS_BY_TYPE[:lower], CHARS_BY_TYPE[:upper] or CHARS_BY_TYPE[:digit]) at a random location in the string we are constructing, with the restriction that neither the preceding nor following character is the same character.
def insert_in_string(str, ch)
i = loop do
i = rand(str.size 1)
next if ch == str[i]
break i if i.zero? || ch != str[i-1]
end
str.insert(i, ch)
end
For example, if we were to insert the character '0' into (a copy of) our string s (which is not needed):
insert_in_string(s.dup, '0')
#=> "arN64kDw6ClzcN0Mj8WAkj1NJC2B5oFoRlcXl5S"
s #=> "arN64kDw6ClzcNMj8WAkj1NJC2B5oFoRlcXl5S"
^
這會在索引處的字符ch之前插入字符。如果在的最后一個字符之后插入回傳。strirand(str.size 1)str.size chstr
在此操作之后,最后一步是使用該方法append_random_char將字串構建為所需的長度。
完成的main方法如下。
def random_string(str_len)
raise ArgumentError if str_len < 3
s = (str_len - 2).times.with_object('') { |_,s| s << append_random_char(s[-1]) }
types_to_add(s).each { |type| insert_in_string(s, CHARS_BY_TYPE[type].sample) }
(str_len - s.size).times { s << append_random_char(s[-1]) }
s
end
s = random_string(40)
#=> "PtQrVFZWUYFwiwRy3ySfAy42G1NT98J6cMVMaWeT"
s.match?(/[a-z]/)
#=> true
s.match?(/[A-Z]/)
#=> true
s.match?(/\d/)
#=> true
s.size
#=> 40
uj5u.com熱心網友回復:
這就是我的做法(警告:未經測驗。只想介紹我的演算法的想法)。我首先為生成的隨機字串的長度取一個亂數(長度在 4 到 16 個字符之間)。然后我隨機確定其中有多少是大寫/小寫/數字,并根據這些決定生成字串,確保我不會連續得到任何重復。
uchars=('A'..'Z').to_a
lchars=('a'..'z').to_a
dchars=('0'..'9').to_a
charmap = { u: uchars, l: lchars, d: dchars }
total_length=rand(13) 4 # Total length of string to be generated
total_u=rand(total_length-3) 1 # Total number of uchars to be generated
total_l=rand(total_length-total_u-2) 1 # Total number of lchars
total_d=total_length-total_u-total_l # Total number of digits
# Array of types to generate
chartypes=([:u]*total_u [:l]*total_l [:d]*total_d).shuffle
# chartypes is an array similar to [:u,:d,:d,:l,:u], where the
# symbols designate the kind of character to be generated.
# outstr : random string to be generated
outstr = charmap[chartypes.first].sample
last_char = outstr.dup
total_length.times do |index|
loop do
nextchar = charmap[chartypes[index]].sample
if nextchar != last_char
outstr << nextchar
last_char = nextchar
break
end
end
end
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/422148.html
標籤:
下一篇:秒表不會停止
