module StringDerivedRandom
Constants
- VERSION
Public Instance Methods
is_one_in?(n, string_seed:)
click to toggle source
For quick bucketing of “process one in N” objects
# File lib/string_derived_random.rb, line 9 def is_one_in?(n, string_seed:) raise ArgumentError if n < 1 new(string_seed).rand(1..n) == 1 end
new(string_seed)
click to toggle source
The objective here is getting a stable random number based on a given string. We use the string to generate a big Integer that can be used to seed a Random object at creation. This allows us to experiment by, say, applying something to
'every 100th of some class of objects having this identifier',
with the result being exactly the same for that identifier, every time. @param string_seed[#to_s] An object that can be converted into a String @return [Random] A seeded Random object
# File lib/string_derived_random.rb, line 25 def new(string_seed) # Compute a digest that gives us a good # distribution of values. Doesn't matter which # digest gets used since it is the distribution # that matters, as well as consistency and a broader # range of possible values digest_bytes = Digest::SHA256.digest(string_seed.to_s) # We get 256 bits of information from the digest. # The Mersenne twister can be seeded with values # in a certain range, after which the seed rolls over. # For the gory details read https://stackoverflow.com/a/20082583/153886 # but basically the range is this: # # 2 ** ( 624 * 32 ) # # which is actually 19968 bits of available values, quite a bit more # than what the SHA256 gives us - which is only 256 bits. # So for our purposes we can just use those values and relax, as there # is no requirement for this seed to be cryptographically-secure. # https://stackoverflow.com/a/17556861/153886 for the bytes -> bigint part seed_int = digest_bytes.bytes.inject {|a, b| (a << 8) + b } Random.new(seed_int) end