brabuhr
8/17/2008 4:03:00 PM
On Fri, Aug 15, 2008 at 11:33 AM, Matthew Moss <matthew.moss@gmail.com> wrote:
> ## Not So Random (#173)
>
> The first part is to create a wrapper around the random number
> generator `rand`, supporting the appropriate parameter (i.e. the
> parameter intrinsic to `rand`). Your wrapper should implement two
> additional functions: `next` which returns the next random number, and
> `reset` which restarts the sequence.
>
> The second part is a little trickier: creating multiple, concurrent,
> _reproducible_ sequences of pseudorandom numbers isn't so easy. As
> convenient as the built-in generator is, there is only one seed.
Since a single Ruby process only has one PRNG, slave off an extra
process for each Random class:
#!/usr/bin/env ruby
require 'rubygems'
require 'slave'
class Random
def initialize(ceiling, seed = nil)
@ceiling = ceiling
@seed = seed || rand(2112)
@slave = Slave::new{
lambda {|reset|
if reset
srand(@seed)
else
rand(@ceiling)
end
}
}
self.reset
end
def next
@slave.object.call(false)
end
def reset
@slave.object.call(true)
end
end
require 'test/unit'
class RandomTest < Test::Unit::TestCase
def test_001
x = Random.new(100, 2112)
assert_equal( [38, 1, 5, 57, 11], Array.new(5) { x.next })
assert_equal( [ 1, 31, 3, 56, 14], Array.new(5) { x.next })
x.reset
assert_equal( [38, 1, 5, 57, 11], Array.new(5) { x.next })
end
def test_002
x = Random.new(100, 2112)
assert_equal( [38, 1, 5, 57, 11], Array.new(5) { x.next })
y = Random.new(100, 1221)
assert_equal( [ 5, 99, 88, 48, 86], Array.new(5) { y.next })
x.reset
assert_equal( [38, 1, 5, 57, 11], Array.new(5) { x.next })
assert_equal( [34, 28, 72, 77, 87], Array.new(5) { y.next })
assert_equal( [ 1, 31, 3, 56, 14], Array.new(5) { x.next })
end
end
Loaded suite foo
Started
.
Finished in 0.251163 seconds.
2 tests, 8 assertions, 0 failures, 0 errors