Here’s my final version in case anyone’s interested:
class Array
def randomize!(seed=nil)
srand(seed) if seed
i = length - 1
while (i > 0) #have to specify Kernel::rand to avoid method name clash
j = Kernel::rand(i)
# Swap self[i] and self[j]
tmp = self[i]
self[i] = self[j]
self[j] = tmp
i -= 1
end #reset srand
srand if seed
self
end
def randomize(seed=nil)
self.dup.randomize!(seed)
end
end
I encountered a puzzling gotcha with rand - it turns out that Rails
monkey-patches Array with ‘rand’ (no arguments) which pulls out a random
element. So, calling
j = rand(i)
was giving me a ‘too many arguments’ error, as it thought i was wanting
Array::rand. So, i just specify that i want Kernel::rand and it’s fine.
1000.times { puts “yes!” if [1,2].randomize == [1,2] }
=> 1000
David
Well spotted - this is the offending line:
j = Kernel::rand(i)
It means (effectively) that a number can never stay in the same place,
which breaks the randomness a bit (and totally breaks it for two-element
arrays). Changing it to this