Reputation: 16627
From some StackOverflow answer I have that neat little function to generate a 10 character String with only a-z and 0-9 chars:
rand(36**10).to_s(36)
The problem is that it sometimes fails and only generates 9 characters. But I really like the ease and speed of it. Any suggestions how to fix it so that I can be sure that it always generates exactly 10 characters? (Without any loops or checking.)
Upvotes: 2
Views: 688
Reputation: 160551
Starting with the idea of using rand(36**5)
by @Mark Rushakoff, this shuffles the zero-padded string to randomize the characters:
('%010x' % [rand(36**5)]).chars.to_a.shuffle.join # => "4a04020701"
('%010x' % [rand(36**5)]).chars.to_a.shuffle.join # => "0e092f0a03"
('%010x' % [rand(36**5)]).chars.to_a.shuffle.join # => "03e240e800"
To work around Ruby not allowing zero-padded strings in the format
I have to switch to padding in the method chain, which is basically what Mark did. To avoid strings of leading zeros this breaks it back down to an array and shuffles the string and rejoins it.
rand(36**5).to_s(36).rjust(10, '0').chars.to_a.shuffle.join # => "e80000h00b"
rand(36**5).to_s(36).rjust(10, '0').chars.to_a.shuffle.join # => "00bv0dy00p"
rand(36**5).to_s(36).rjust(10, '0').chars.to_a.shuffle.join # => "v0hw000092"
Upvotes: 0
Reputation: 4060
This will generate a random string of characters and numbers but no single character will appear more than once
(('a'..'z').to_a + (0..9).to_a).shuffle[1..10].join
To "fix" the number of possible outcomes you just do this:
a = (('a'..'z').to_a + (0..9).to_a)
a = a * 10
p a.shuffle[1..10].join
Upvotes: 0
Reputation: 5166
how about:
>> require 'md5'
=> true
>> MD5::hexdigest(Time.now.to_f.to_s)[0..9]
=> "89d83d3516"
Upvotes: 0
Reputation: 258188
When you randomly generate a number less than 369, it ends up being a 9-character string. Left-pad it with zeros:
rand(36**10).to_s(36).rjust(10, "0")
Example:
irb(main):018:0> (36**9).to_s(36)
=> "1000000000"
irb(main):019:0> (36**9 - 1).to_s(36)
=> "zzzzzzzzz"
irb(main):020:0> (36**5).to_s.rjust(10, "0")
=> "0060466176"
Upvotes: 5