loaded_die 1.0.2 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/LICENSE.txt CHANGED
@@ -1,4 +1,4 @@
1
- Copyright (c) 2022 Aaron Beckerman
1
+ Copyright (c) 2024 Aaron Beckerman
2
2
 
3
3
  Permission is hereby granted, free of charge, to any person obtaining a copy of
4
4
  this software and associated documentation files (the "Software"), to deal in
data/README.txt ADDED
@@ -0,0 +1,47 @@
1
+ Loaded Die
2
+
3
+ Loaded Die is a Ruby library that makes it easy to randomly choose from a set
4
+ of options where some options are more likely than others.
5
+
6
+
7
+ Usage
8
+
9
+ This is the basic pattern: First, you load the library. Then you create an
10
+ instance of LoadedDie::Sampler and send the sample message to it as many
11
+ times as you like.
12
+
13
+ Let's say you want to choose randomly from three strings: "A", "B", and "C".
14
+ You want "A" and "B" to be equally likely, and "C" to be twice as likely as one
15
+ of them. That means "A" should be 25% likely, B should be 25% likely, and C
16
+ should be 50% likely.
17
+
18
+ You can create your sampler like this:
19
+
20
+ require "loaded_die"
21
+ sampler = LoadedDie::Sampler.new({ "A" => 0.25, "B" => 0.25, "C" => 0.5 })
22
+
23
+ And then sample from it like this:
24
+
25
+ sampler.sample
26
+
27
+ But you don't need to be fussy about how you represent probabilities. That is,
28
+ you don't need to represent them as numbers between zero and one such that they
29
+ sum to one. Their relative values are what matter. Furthermore, they don't need
30
+ to be floats, just objects that convert to floats. So you could also create
31
+ your sampler like this:
32
+
33
+ sampler = LoadedDie::Sampler.new({ "A" => 1, "B" => 1, "C" => 2 })
34
+
35
+ You can specify the random number generator that sample uses. To do this,
36
+ supply as the argument a hash with your random number generator under the
37
+ :random key. (This is based on the behavior of Ruby's Array#sample.) Your
38
+ random number generator will be sent a rand message with one argument, the sum
39
+ of the weights you specified when creating the sampler. The returned object
40
+ must be a float greater than or equal to zero and less than the sum of the
41
+ weights.
42
+
43
+ rng = Object.new
44
+ def rng.rand(n)
45
+ 0.0
46
+ end
47
+ sampler.sample({ :random => rng })
data/lib/loaded_die.rb CHANGED
@@ -1,80 +1,79 @@
1
1
  ##
2
- # This module provides a class for randomly choosing from a set of options
3
- # where some options are more likely than others.
4
- #
5
- module LoadedDie
2
+ # This module allows you to choose randomly from a set of options where some
3
+ # options are more likely than others.
6
4
 
7
- ##
8
- # The version string.
9
- #
10
- VERSION = '1.0.2'
5
+ module LoadedDie
11
6
 
12
7
  ##
13
- # Objects of this class can choose randomly from a set of options (called
8
+ # Instances of this class can choose randomly from a set of options (called
14
9
  # individuals here). The options can have different probabilities of being
15
10
  # chosen.
16
- #
11
+
17
12
  class Sampler
18
13
 
19
14
  ##
20
- # The default random number generator.
21
- #
15
+ # The default random number generator. It samples from a uniform
16
+ # distribution.
17
+
22
18
  DEFAULT_RNG = ::Object.new
23
- def DEFAULT_RNG.rand(n)
19
+ def DEFAULT_RNG.rand n
24
20
  ::Kernel.rand * n
25
21
  end
26
22
 
27
23
  ##
28
- # A class representing a segment of the number line with an associated
29
- # individual.
30
- #
31
- Segment = ::Struct.new(:maximum, :individual)
24
+ # Creates a sampler from a population. The argument should return an
25
+ # enumerable (conventionally an instance of Enumerator) of arrays when sent
26
+ # a to_enum message with no arguments. (A normal instance of Hash
27
+ # qualifies.) Each array must have at least two elements: the first element
28
+ # is an individual that can be chosen and the second element is its weight
29
+ # -- that is, the likelihood relative to the other weights that the
30
+ # individual will be chosen. Weights must convert to finite floats that are
31
+ # zero or positive.
32
32
 
33
- ##
34
- # Creates a sampler from a population. The argument should be an enumerable
35
- # of two-element arrays (a hash qualifies). The first element of each array
36
- # is an individual that can be chosen; the second element is its weight --
37
- # that is, the likelihood (relative to the other weights) that the
38
- # individual will be chosen. Weights must be positive numbers.
39
- #
40
- def initialize(population)
41
- @compiled = population.inject [] do |accum, (individual, weight)|
42
- if weight <= 0
43
- raise ::ArgumentError, "non-positive weight #{weight}"
33
+ def initialize population
34
+ @compiled = population.to_enum.inject [] do |accum, elem|
35
+ individual = elem.fetch 0
36
+ weight = elem.fetch 1
37
+ weight_f = ::Kernel.Float weight
38
+ unless 0.0 <= weight_f && weight_f.finite?
39
+ ::Kernel.raise ::ArgumentError, "invalid weight #{weight_f}"
40
+ break
44
41
  end
45
42
  prev_max =
46
43
  if last = accum.last
47
- last.maximum
44
+ last.fetch :maximum
48
45
  else
49
- 0
46
+ 0.0
50
47
  end
51
- accum << Segment.new(prev_max + weight, individual)
48
+ accum << { :maximum => prev_max + weight_f, :individual => individual }
52
49
  end
53
50
  nil
54
51
  end
55
52
 
56
53
  ##
57
54
  # Returns the sum of weights.
58
- #
55
+
59
56
  def length
60
57
  if last = @compiled.last
61
- last.maximum
58
+ last.fetch :maximum
62
59
  else
63
- 0
60
+ 0.0
64
61
  end
65
62
  end
66
63
 
67
64
  ##
68
- # Returns the individual for the given point. The point should be a number.
69
- # If it is greater than or equal to zero and less than the sum of weights,
70
- # this returns the corresponding individual. If it is outside those bounds,
71
- # this returns nil.
72
- #
73
- def [](point)
74
- if point < 0
65
+ # Returns the individual associated with the given point on a line. The
66
+ # point should convert to a float. If it is greater than or equal to zero
67
+ # and less than the sum of weights, this returns the corresponding
68
+ # individual. If it is outside those bounds, this returns nil.
69
+
70
+ def [] point
71
+ point_f = ::Kernel.Float point
72
+ if 0.0 > point_f
75
73
  nil
76
- elsif choice = @compiled.detect { |segment| point < segment.maximum }
77
- choice.individual
74
+ elsif choice = @compiled.detect { |segment|
75
+ segment.fetch(:maximum) > point_f }
76
+ choice.fetch :individual
78
77
  else
79
78
  nil
80
79
  end
@@ -82,16 +81,18 @@ module LoadedDie
82
81
 
83
82
  ##
84
83
  # Returns a randomly-chosen individual. The argument is a hash, empty by
85
- # default. If it contains a value for the +:random+ key, that value will
86
- # be used as the random number generator instead of the default. This RNG
87
- # will be sent a "rand" message with one argument, the sum of weights, and
88
- # should return a number greater than or equal to zero and less than the
89
- # sum of weights.
90
- #
91
- def sample(options = {})
92
- rng = options.fetch(:random) { DEFAULT_RNG }
93
- point = rng.rand(length)
84
+ # default. If it contains a value for the +:random+ key, that value will be
85
+ # used as the random number generator instead of the default. This RNG will
86
+ # be sent a rand message with one argument, the sum of weights, and should
87
+ # return a number (convertible to a float) greater than or equal to zero
88
+ # and less than the sum of weights.
89
+
90
+ def sample options = {}
91
+ rng = options.fetch(:random) { ::LoadedDie::Sampler::DEFAULT_RNG }
92
+ point = rng.rand length
94
93
  self[point]
95
94
  end
95
+
96
96
  end
97
+
97
98
  end
data/loaded_die.gemspec CHANGED
@@ -1,19 +1,12 @@
1
- # -*- encoding: utf-8 -*-
2
- lib = File.expand_path("../lib", __FILE__)
3
- $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
- require "loaded_die"
5
-
6
1
  Gem::Specification.new do |s|
7
2
  s.name = "loaded_die"
8
- s.version = LoadedDie::VERSION
9
- s.author = "Aaron Beckerman"
10
- s.summary = %q{A library for choosing randomly where some options are more likely than others.}
11
- s.description = %q{Loaded Die is a library that makes it easy to choose randomly from a set of options where some options are more likely than others.}
12
- s.license = "MIT"
13
- s.platform = Gem::Platform::RUBY
3
+ s.version = "2.0.0"
4
+ s.authors = ["Aaron Beckerman"]
5
+ s.summary = "A library for choosing randomly where some options are more" \
6
+ " likely than others."
7
+ s.licenses = ["MIT"]
14
8
  s.required_ruby_version = ">= 1.8.7"
15
- s.files = ["LICENSE.txt", "README.rdoc", "loaded_die.gemspec", "lib/loaded_die.rb", "test/loaded_die_test.rb"]
9
+ s.files = ["LICENSE.txt", "README.txt", "loaded_die.gemspec",
10
+ "lib/loaded_die.rb", "test/loaded_die_test.rb"]
16
11
  s.test_files = ["test/loaded_die_test.rb"]
17
- s.executables = []
18
- s.require_paths = ["lib"]
19
12
  end
@@ -1,69 +1,195 @@
1
- require 'loaded_die'
1
+ # Sections that create local variables are in class definitions so that later
2
+ # sections cannot accidentally reference those local variables.
2
3
 
3
- String == LoadedDie::VERSION.class or fail
4
+ require "loaded_die"
4
5
 
5
- Module == LoadedDie.class or fail
6
+ # LoadedDie should be an instance of Module.
7
+ fail "" unless Module.equal? LoadedDie.class
6
8
 
7
- Class == LoadedDie::Sampler.class or fail
9
+ # LoadedDie::Sampler should be a class.
10
+ fail "" unless Class.equal? LoadedDie::Sampler.class
8
11
 
12
+ # LoadedDie::Sampler::DEFAULT_RNG.rand should return a float in the expected
13
+ # range.
14
+ class ::Object
15
+ n = LoadedDie::Sampler::DEFAULT_RNG.rand 0.5
16
+ fail "" unless Float.equal? n.class
17
+ fail "" unless 0.0 <= n && 0.5 > n
18
+ end
19
+
20
+ # LoadedDie::Sampler.new with an empty population should return an object of
21
+ # class LoadedDie::Sampler.
22
+ fail "" unless LoadedDie::Sampler.equal? LoadedDie::Sampler.new({}).class
23
+
24
+ # LoadedDie::Sampler.new with only zero or positive finite weights should
25
+ # return an instance of LoadedDie::Sampler.
26
+ fail "" unless LoadedDie::Sampler.equal?(
27
+ LoadedDie::Sampler.new({ :a => 0.0, :b => 1.0 }).class)
28
+
29
+ # LoadedDie::Sampler.new with a negative weight should raise an exception.
30
+ begin
31
+ LoadedDie::Sampler.new({ :a => -1.0 })
32
+ rescue ArgumentError
33
+ fail "" unless /\Ainvalid weight / =~ $!.message
34
+ else
35
+ fail ""
36
+ end
37
+
38
+ # LoadedDie::Sampler.new with a NaN weight should raise an exception.
9
39
  begin
10
- LoadedDie::Sampler.new(:a => 0)
40
+ LoadedDie::Sampler.new({ :a => 0.0 / 0.0 })
11
41
  rescue ArgumentError
42
+ fail "" unless /\Ainvalid weight / =~ $!.message
12
43
  else
13
- fail
44
+ fail ""
14
45
  end
15
46
 
47
+ # LoadedDie::Sampler.new with an infinite weight should raise an exception.
16
48
  begin
17
- LoadedDie::Sampler.new(:a => -1)
49
+ LoadedDie::Sampler.new({ :a => 1.0 / 0.0 })
18
50
  rescue ArgumentError
51
+ fail "" unless /\Ainvalid weight / =~ $!.message
19
52
  else
20
- fail
53
+ fail ""
21
54
  end
22
55
 
23
- lambda do
56
+ # LoadedDie::Sampler.new with a weight that does not convert to a float should
57
+ # raise an exception.
58
+ begin
59
+ LoadedDie::Sampler.new({ :a => nil })
60
+ rescue TypeError
61
+ else
62
+ fail ""
63
+ end
64
+
65
+ # LoadedDie::Sampler.new with a population that doesn't conform to the
66
+ # interface should raise an exception.
67
+ begin
68
+ LoadedDie::Sampler.new nil
69
+ rescue NoMethodError
70
+ else
71
+ fail ""
72
+ end
73
+ begin
74
+ LoadedDie::Sampler.new [[]]
75
+ rescue IndexError
76
+ else
77
+ fail ""
78
+ end
79
+ begin
80
+ LoadedDie::Sampler.new [[1.0]]
81
+ rescue IndexError
82
+ else
83
+ fail ""
84
+ end
85
+
86
+ # Sending new with superfluous non-block arguments to LoadedDie::Sampler should
87
+ # raise an exception.
88
+ begin
89
+ LoadedDie::Sampler.new({}, nil)
90
+ rescue ArgumentError
91
+ else
92
+ fail ""
93
+ end
94
+
95
+ # A sampler should say it responds to the expected messages.
96
+ class ::Object
24
97
  sampler = LoadedDie::Sampler.new({})
25
- sampler.respond_to?(:length) or fail
26
- sampler.respond_to?(:[]) or fail
27
- sampler.respond_to?(:sample) or fail
28
- end.call
98
+ fail "" unless sampler.respond_to? :length
99
+ fail "" unless sampler.respond_to? :[]
100
+ fail "" unless sampler.respond_to? :sample
101
+ end
29
102
 
30
- 0 == LoadedDie::Sampler.new({}).length or fail
31
- 2 == LoadedDie::Sampler.new({ :a => 2 }).length or fail
32
- (2 + 3.1) == LoadedDie::Sampler.new({ :a => 2, :b => 3.1 }).length or fail
103
+ # Sampler length should be the sum of weights converted to floats.
104
+ fail "" unless 0.0 == LoadedDie::Sampler.new([]).length
105
+ fail "" unless 2.0 == LoadedDie::Sampler.new([[:a, 2.0]]).length
106
+ fail "" unless (Float(2) + 0.0 + 3.1) ==
107
+ LoadedDie::Sampler.new([[:a, 2], [:b, 0.0], [:c, 3.1]]).length
108
+
109
+ # Sending length with superfluous non-block arguments to a sampler should raise
110
+ # an exception.
111
+ begin
112
+ LoadedDie::Sampler.new({}).length nil
113
+ rescue ArgumentError
114
+ else
115
+ fail ""
116
+ end
33
117
 
34
- lambda do
118
+ # An empty sampler should always find nil when queried.
119
+ class ::Object
35
120
  sampler = LoadedDie::Sampler.new({})
36
- nil == sampler[0.42] or fail
37
- end.call
38
-
39
- lambda do
40
- sampler = LoadedDie::Sampler.new([[:a, 3], [:b, 2.0], [:c, 5]])
41
- nil == sampler[-1.0] or fail
42
- :a == sampler[0.0] or fail
43
- :a == sampler[2.99] or fail
44
- :b == sampler[3] or fail
45
- :b == sampler[3.0] or fail
46
- :b == sampler[4.99] or fail
47
- :c == sampler[5.0] or fail
48
- :c == sampler[9.99] or fail
49
- nil == sampler[10.0] or fail
50
- nil == sampler[11.0] or fail
51
- end.call
52
-
53
- lambda do
121
+ fail "" unless nil.equal? sampler[0.42]
122
+ end
123
+
124
+ # A sampler should find the expected segment or nil when queried.
125
+ class ::Object
126
+ sampler = LoadedDie::Sampler.new [[:a, 3], ["!", 0.0], [:b, 2.0], [:c, 5]]
127
+ fail "" unless nil.equal? sampler[-1.0]
128
+ fail "" unless :a.equal? sampler[0.0]
129
+ fail "" unless :a.equal? sampler[2.9]
130
+ fail "" unless :b.equal? sampler[3.0]
131
+ fail "" unless :b.equal? sampler[4.9]
132
+ fail "" unless :c.equal? sampler[5.0]
133
+ fail "" unless :c.equal? sampler[9.9]
134
+ fail "" unless nil.equal? sampler[10.0]
135
+ fail "" unless nil.equal? sampler[11.0]
136
+ fail "" unless nil.equal? sampler[0.0 / 0.0] # NaN
137
+ fail "" unless nil.equal? sampler[1.0 / 0.0] # infinity
138
+
139
+ # This non-float should be converted to a float.
140
+ fail "" unless :b.equal? sampler[4]
141
+
142
+ # An exception should be raised when the argument cannot be converted to a
143
+ # float.
144
+ begin
145
+ sampler[nil]
146
+ rescue TypeError
147
+ else
148
+ fail ""
149
+ end
150
+ end
151
+
152
+ # Sending [] with superfluous non-block arguments to a sampler should raise an
153
+ # exception.
154
+ begin
155
+ LoadedDie::Sampler.new({})[0.0, nil]
156
+ rescue ArgumentError
157
+ else
158
+ fail ""
159
+ end
160
+
161
+ # An empty sampler should return nil when sampled with the default
162
+ # random number generator.
163
+ class ::Object
54
164
  sampler = LoadedDie::Sampler.new({})
55
- nil == sampler.sample or fail
56
- end.call
165
+ fail "" unless nil.equal? sampler.sample
166
+ end
57
167
 
58
- lambda do
59
- sampler = LoadedDie::Sampler.new([[:a, 3], [:b, 2.0], [:c, 9001]])
168
+ # A sampler should return the expected individual when the random number
169
+ # generator is faked and it should return something reasonable when sampled
170
+ # with the default random number generator.
171
+ class ::Object
172
+ sampler = LoadedDie::Sampler.new [[:a, 3], [:b, 2.0], ["!", 0.0], [:c, 9001]]
60
173
  rng = Object.new
61
- def rng.rand(n)
62
- (3 + 2.0 + 9001) == n or fail
63
- 4.99
174
+ def rng.rand n
175
+ fail "" unless ((Float(3) + 2.0) + Float(9001)) == n
176
+ 4.9
64
177
  end
65
- :b == sampler.sample(:random => rng) or fail
66
- [:a, :b, :c].include?(sampler.sample) or fail
67
- end.call
178
+ fail "" unless :b.equal? sampler.sample({ :random => rng })
179
+ fail "" unless [:a, :b, :c].include? sampler.sample
180
+ # Unknown options should be ignored.
181
+ fail "" unless :b.equal? sampler.sample({ :random => rng, "?" => "?" })
182
+ fail "" unless [:a, :b, :c].include? sampler.sample({ "?" => "?" })
183
+ end
184
+
185
+ # Sending sample with superfluous non-block arguments to a sampler should raise
186
+ # an exception.
187
+ begin
188
+ LoadedDie::Sampler.new({}).sample({}, nil)
189
+ rescue ArgumentError
190
+ else
191
+ fail ""
192
+ end
68
193
 
69
- puts 'Test finished.'
194
+ # If this message doesn't get written, there was a problem.
195
+ puts "Test finished: #{__FILE__}"
metadata CHANGED
@@ -1,49 +1,73 @@
1
- --- !ruby/object:Gem::Specification
1
+ --- !ruby/object:Gem::Specification
2
2
  name: loaded_die
3
- version: !ruby/object:Gem::Version
4
- version: 1.0.2
3
+ version: !ruby/object:Gem::Version
4
+ hash: 15
5
+ prerelease:
6
+ segments:
7
+ - 2
8
+ - 0
9
+ - 0
10
+ version: 2.0.0
5
11
  platform: ruby
6
- authors:
12
+ authors:
7
13
  - Aaron Beckerman
8
14
  autorequire:
9
15
  bindir: bin
10
16
  cert_chain: []
11
- date: 2022-12-01 00:00:00.000000000 Z
17
+
18
+ date: 2024-03-12 00:00:00 -07:00
19
+ default_executable:
12
20
  dependencies: []
13
- description: Loaded Die is a library that makes it easy to choose randomly from a
14
- set of options where some options are more likely than others.
21
+
22
+ description:
15
23
  email:
16
24
  executables: []
25
+
17
26
  extensions: []
27
+
18
28
  extra_rdoc_files: []
19
- files:
29
+
30
+ files:
20
31
  - LICENSE.txt
21
- - README.rdoc
22
- - lib/loaded_die.rb
32
+ - README.txt
23
33
  - loaded_die.gemspec
34
+ - lib/loaded_die.rb
24
35
  - test/loaded_die_test.rb
36
+ has_rdoc: true
25
37
  homepage:
26
- licenses:
38
+ licenses:
27
39
  - MIT
28
- metadata: {}
29
40
  post_install_message:
30
41
  rdoc_options: []
31
- require_paths:
42
+
43
+ require_paths:
32
44
  - lib
33
- required_ruby_version: !ruby/object:Gem::Requirement
34
- requirements:
45
+ required_ruby_version: !ruby/object:Gem::Requirement
46
+ none: false
47
+ requirements:
35
48
  - - ">="
36
- - !ruby/object:Gem::Version
49
+ - !ruby/object:Gem::Version
50
+ hash: 57
51
+ segments:
52
+ - 1
53
+ - 8
54
+ - 7
37
55
  version: 1.8.7
38
- required_rubygems_version: !ruby/object:Gem::Requirement
39
- requirements:
56
+ required_rubygems_version: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
40
59
  - - ">="
41
- - !ruby/object:Gem::Version
42
- version: '0'
60
+ - !ruby/object:Gem::Version
61
+ hash: 3
62
+ segments:
63
+ - 0
64
+ version: "0"
43
65
  requirements: []
44
- rubygems_version: 3.1.6
66
+
67
+ rubyforge_project:
68
+ rubygems_version: 1.6.2
45
69
  signing_key:
46
- specification_version: 4
70
+ specification_version: 3
47
71
  summary: A library for choosing randomly where some options are more likely than others.
48
- test_files:
72
+ test_files:
49
73
  - test/loaded_die_test.rb
checksums.yaml DELETED
@@ -1,7 +0,0 @@
1
- ---
2
- SHA256:
3
- metadata.gz: b04718fe3728aa1a6f354e81eed37708842a79fb62b6151f6d9a2823bccd603e
4
- data.tar.gz: a6993994255411fdcd889aab140e8c8a1cb8453fad9ad44fb972076330409534
5
- SHA512:
6
- metadata.gz: 52d5caf5851d300a185600d5a6e00203bebf672913a78ab42ca4430a369b5d690033fd679ccbef1df8abac7bbdd6c63e77d8f04067f4445142caf4b052e0850c
7
- data.tar.gz: 2d896e03013c765bfe6beec383ffa456e9e4c199573d8b77900d3a7badef92f70d0a90a49e467317b98308b6779246c34e52401aec1d602b7e59e844071ab94b
data/README.rdoc DELETED
@@ -1,57 +0,0 @@
1
- = Loaded Die
2
-
3
- Loaded Die is a Ruby library that makes it easy to randomly choose from a set
4
- of options where some options are more likely than others.
5
-
6
-
7
- == Usage
8
-
9
- This is the basic pattern: First, you load the library. Then you create an
10
- instance of LoadedDie::Sampler and send the "sample" message to it as many
11
- times as you like.
12
-
13
- Let's say you want to choose randomly from three strings: "A", "B", and "C".
14
- You want "A" and "B" to be equally likely, and "C" to be twice as likely as one
15
- of them. That means "A" should be 25% likely, B should be 25% likely, and C
16
- should be 50% likely.
17
-
18
- You can create your sampler like this:
19
-
20
- require 'loaded_die'
21
- sampler = LoadedDie::Sampler.new('A' => 0.25, 'B' => 0.25, 'C' => 0.5)
22
-
23
- And then sample from it like this:
24
-
25
- sampler.sample
26
-
27
- But you don't have to be fussy about how you represent probabilities. That is,
28
- you don't need to represent them as numbers between 0 and 1 such that they sum
29
- up to 1. Their relative values are what matter. So you could also create your
30
- sampler like this:
31
-
32
- sampler = LoadedDie::Sampler.new('A' => 1, 'B' => 1, 'C' => 2)
33
-
34
- You can specify the random number generator that sample uses. To do this,
35
- supply as the argument a hash with your random number generator under the
36
- +:random+ key. (This is based on the behavior of Ruby's Array#sample.) Your
37
- random number generator will be sent a "rand" message with one argument, the
38
- sum of the weights you specified when creating the sampler. The return value
39
- must be a number greater than or equal to zero and less than the sum of the
40
- weights.
41
-
42
- rng = Object.new
43
- def rng.rand(n)
44
- 0
45
- end
46
- sampler.sample(:random => rng)
47
-
48
-
49
- == Author
50
-
51
- This was written by Aaron Beckerman.
52
-
53
-
54
- == Copyright
55
-
56
- This code is distributed under the MIT License (also known as the Expat
57
- License). See the LICENSE.txt file for details.