Class: PickMeToo
- Inherits:
-
Object
- Object
- PickMeToo
- Defined in:
- lib/pick_me_too.rb
Overview
An “urn” from which you can pick things with specified frequencies.
require 'pick_me_too'
wandering_monsters = PickMeToo.new({goblin: 10, bugbear: 2, orc: 5, spider: 3, troll: 1})
10.times.map { wandering_monsters.pick }
# => [:goblin, :orc, :bugbear, :orc, :goblin, :bugbear, :goblin, :goblin, :orc, :goblin]
irrational = PickMeToo.new({e: Math::E, pi: Math::PI})
to.times.map { irrational.pick }
# => [:e, :e, :e, :pi, :e, :e, :e, :pi, :pi, :e]
Items once picked are “placed back in the urn”, so if you pick a cat this doesn’t reduce the probability the next thing you pick is also a cat, and the urn will never be picked empty. (And of course this is all a metaphor.)
Defined Under Namespace
Classes: Error
Constant Summary collapse
- VERSION =
'1.1.1'
Instance Method Summary collapse
-
#initialize(frequencies, rnd = -> { rand }) ⇒ PickMeToo
constructor
“Fill” the urn.
-
#pick ⇒ Object
Pick an item from the urn.
-
#randomize!(rnd = -> { rand }) ⇒ Object
Replace the random number generator.
Constructor Details
#initialize(frequencies, rnd = -> { rand }) ⇒ PickMeToo
“Fill” the urn.
The required frequencies parameter must be something that is effectively a list of pairs: things to pick paired with their frequency. The “frequency” is just any positive number.
The optional rnd parameter is a Proc that when called returns a number, ideally in the interval [0, 1]. This parameter allows you to provided a seeded random number generator, so the choices occur in a predictable sequence, which is useful for testing.
This constructor method will raise a ‘PickMeToo::Error` if
-
there are no pairs in the frequency list
-
any of the frequencies is non-positive
-
any of the items in the list isn’t something followed by a number
38 39 40 41 42 43 44 45 46 47 48 49 |
# File 'lib/pick_me_too.rb', line 38 def initialize(frequencies, rnd = -> { rand }) @rnd = rnd frequencies = prepare(Array(frequencies)) @objects = frequencies.map(&:first) if @objects.length == 1 @picker = ->(_p) { 0 } else root = balanced_binary_tree(frequencies) # compile everything into a nested ternary expression @picker = eval "->(p) { #{ternarize(root, 0)} }" end end |
Instance Method Details
#pick ⇒ Object
Pick an item from the urn.
53 54 55 |
# File 'lib/pick_me_too.rb', line 53 def pick @objects[@picker.call(@rnd.call)] end |
#randomize!(rnd = -> { rand }) ⇒ Object
Replace the random number generator.
If the optional argument is omitted, the replacement is just
-> { rand }
This is useful if you want to switch from a seeded random number generator to something more truly random.
66 67 68 |
# File 'lib/pick_me_too.rb', line 66 def randomize!(rnd = -> { rand }) @rnd = rnd end |