Class: Forall::Random
- Inherits:
-
Object
- Object
- Forall::Random
- Defined in:
- lib/forall/random.rb
Instance Method Summary collapse
-
#array(size: nil) ⇒ Object
Generates an Array by repeatedly calling a block that returns a random value.
- #boolean ⇒ TrueClass | FalseClass
-
#date(range = nil) ⇒ Date
Returns a randomly chosen Date within the given bounds.
-
#datetime(range = nil) ⇒ DateTime
Returns a randomly chosen DateTime within the given bounds.
-
#float(range = nil) ⇒ Float
Returns a randomly chosen floating point number.
-
#hash(size: nil) {|| ... } ⇒ Hash<K, V>
Generates a Hash by repeatedly calling a block that returns a random [key, val] pair.
-
#initialize(seed: nil) ⇒ Random
constructor
A new instance of Random.
-
#integer(range = nil) ⇒ Integer
Returns a randomly chosen integer within the given bounds.
-
#permutation(size: nil) ⇒ Array<Integer>
Generates a random permutation of the given size.
-
#range(range, width: nil) ⇒ Range
Returns a randomly chosen range within the given bounds.
-
#sample(items, count: nil) ⇒ Object
(also: #choose)
Returns a uniformly random chosen element(s) from the given Enumerable.
- #seed ⇒ Integer
- #set(size: nil) ⇒ Object
- #shuffle(items) ⇒ Array<A>
-
#time(range = nil, utc: nil) ⇒ Time
Returns a randomly chosen Time within the given bounds.
-
#weighted(items, freqs, count: nil) ⇒ Object
Returns a uniformly random chosen element(s) from the given Enumerable.
Constructor Details
#initialize(seed: nil) ⇒ Random
Returns a new instance of Random.
5 6 7 |
# File 'lib/forall/random.rb', line 5 def initialize(seed: nil) @prng = ::Random.new(seed || ::Random.new_seed) end |
Instance Method Details
#array(size: nil) ⇒ Object
Generates an Array by repeatedly calling a block that returns a random value.
247 248 249 250 251 |
# File 'lib/forall/random.rb', line 247 def array(size: nil) size ||= integer(0..64) size = choose(size) if Range === size size.times.map{|n| yield n } end |
#boolean ⇒ TrueClass | FalseClass
15 16 17 |
# File 'lib/forall/random.rb', line 15 def boolean @prng.rand >= 0.5 end |
#date(range = nil) ⇒ Date
Returns a randomly chosen Date within the given bounds
43 44 45 46 47 |
# File 'lib/forall/random.rb', line 43 def date(range = nil) min = (range&.min || Date.civil(0000, 1, 1)).to_time max = (range&.max || Date.civil(9999,12,31)).to_time + 86399 Time.at(float(min.to_f .. max.to_f)).to_date end |
#datetime(range = nil) ⇒ DateTime
Returns a randomly chosen DateTime within the given bounds
69 70 71 72 73 |
# File 'lib/forall/random.rb', line 69 def datetime(range = nil) min = range&.min&.to_time max = range&.max&.to_time time(min..max).to_datetime end |
#float(range = nil) ⇒ Float
Returns a randomly chosen floating point number
33 34 35 36 37 |
# File 'lib/forall/random.rb', line 33 def float(range = nil) min = range&.min || Float::MIN max = range&.max || Float::MAX @prng.rand(min..max) end |
#hash(size: nil) {|| ... } ⇒ Hash<K, V>
Generates a Hash by repeatedly calling a block that returns a random [key, val] pair.
259 260 261 262 263 264 265 266 267 268 269 270 |
# File 'lib/forall/random.rb', line 259 def hash(size: nil) size ||= integer(0..64) size = choose(size) if Range === size hash = {} until hash.size >= size k, v = yield(hash.size) hash[k] = v end hash end |
#integer(range = nil) ⇒ Integer
Returns a randomly chosen integer within the given bounds
23 24 25 26 27 |
# File 'lib/forall/random.rb', line 23 def integer(range = nil) min = range&.min || -2**64-1 max = range&.max || 2**64+1 @prng.rand(min..max) end |
#permutation(size: nil) ⇒ Array<Integer>
Generates a random permutation of the given size
235 236 237 |
# File 'lib/forall/random.rb', line 235 def permutation(size: nil) (0..(size || integer(0..64))-1).to_a.shuffle!(random: @prng) end |
#range(range, width: nil) ⇒ Range
Returns a randomly chosen range within the given bounds
80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 |
# File 'lib/forall/random.rb', line 80 def range(range, width: nil) min = range.min max = range.max if width.nil? case min or max when Float a = float(range) b = float(range) when Integer a = integer(range) b = integer(range) when Time a = time(range) b = time(range) when Date a = date(range) b = date(range) when DateTime a = datetime(range) b = datetime(range) else a, b = choose(range, count: 2) end if a < b min = a max = b else min = b max = a end else # Randomly choose a width within given bounds width = choose(width) if Enumerable === width case min or max when Float min = float(min: min, max: max-width) max = min+width-1 when Integer min = integer(min: min, max: max-width) max = min+width-1 else all = (min..max).to_a max = all.size-1 # Randomly choose element indices min = integer(min: 0, max: max-width) max = min+width-1 min = all[min] max = all[max] end end min..max end |
#sample(items, count: nil) ⇒ Object Also known as: choose
Returns a uniformly random chosen element(s) from the given Enumerable
143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 |
# File 'lib/forall/random.rb', line 143 def sample(items, count: nil) case items when Input items.sample(self, count: count) when Range method = if Integer === (items.min || items.max) then :integer elsif Float === (items.min || items.max) then :float elsif Time === (items.min || items.max) then :time elsif defined?(Date) and Date === (items.min || items.max) then :date elsif defined?(DateTime) and DateTime === (items.min || items.max) then :datetime else # NOTE: This is memory inefficient items = items.to_a if count.nil? return items.sample(random: @prng) else return count.times.map{|_| items.sample(random: @prng) } end end if count.nil? send(method, items) else count.times.map{|_| send(method, items) } end else unless items.respond_to?(:sample) # NOTE: This works across many types but is memory inefficient items = items.to_a end if count.nil? items.sample(random: @prng) else # Sample *with* replacement count.times.map{|_| items.sample(random: @prng) } end end end |
#seed ⇒ Integer
10 11 12 |
# File 'lib/forall/random.rb', line 10 def seed @prng.seed end |
#set(size: nil) ⇒ Object
272 273 274 275 276 277 278 279 280 281 282 |
# File 'lib/forall/random.rb', line 272 def set(size: nil) size ||= integer(0..64) size = choose(size) if Range === size set = Set.new until set.size == size set << yield(set.size) end set end |
#shuffle(items) ⇒ Array<A>
227 228 229 |
# File 'lib/forall/random.rb', line 227 def shuffle(items) items.shuffle(random: @prng) end |
#time(range = nil, utc: nil) ⇒ Time
Returns a randomly chosen Time within the given bounds
53 54 55 56 57 58 59 60 61 62 63 |
# File 'lib/forall/random.rb', line 53 def time(range = nil, utc: nil) min = range&.min || Time.utc(0000,1,1,0,0,0) max = range&.max || Time.utc(9999,12,31,23,59,59) rnd = float(min.to_f .. max.to_f) if utc or (utc.nil? and (min.utc? or max.utc?)) Time.at(rnd).utc else Time.at(rnd) end end |
#weighted(items, freqs, count: nil) ⇒ Object
Returns a uniformly random chosen element(s) from the given Enumerable
193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 |
# File 'lib/forall/random.rb', line 193 def weighted(items, freqs, count: nil) unless items.size == freqs.size raise ArgumentError, "items and frequencies must have same size" end # This runs in O(n) time where n is the number of possible items. This is # not dependent on `count`, the number of requested items. if count.nil? sum = freqs[0].to_f res = items[0] (1..items.size - 1).each do |i| sum += freqs[i] p = freqs[i] / sum j = @prng.rand res = items[i] if j <= p end else sum = freqs[0, count].sum.to_f res = items[0, count] (count..items.size).each do |i| sum += freqs[i] p = count * freqs[i] / sum j = @prng.rand res[@prng.rand(count)] = items[i] if j <= p end end res end |