medihack
medihack

Reputation: 16627

Little random string generator that unfortunately sometimes fails. Please help me fix it

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

Answers (5)

j7sx
j7sx

Reputation: 1

(('a'..'z').to_a + ('A'..'Z').to_a + (0..9).to_a).sample(8).join

Upvotes: 0

the Tin Man
the Tin Man

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

krusty.ar
krusty.ar

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

efalcao
efalcao

Reputation: 5166

how about:

>> require 'md5'
=> true
>> MD5::hexdigest(Time.now.to_f.to_s)[0..9]
=> "89d83d3516"

Upvotes: 0

Mark Rushakoff
Mark Rushakoff

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

Related Questions