可以將隨機數發生器傳遞給Array#shuffle
,這使得混洗具有確定性。交叉執行確定性陣列#shuffle
例如,在MRI 1.9.3p327:
[1, 2, 3, 4].shuffle(random: Random.new(0)) # => [1, 2, 4, 3]
[1, 2, 3, 4].shuffle(random: Random.new(0)) # => [1, 2, 4, 3]
然而,沒有指定隨機的隨機數發生器實現。正因爲如此,Ruby的其他實現有不同的結果。
在Rubinius的2.0.0rc1(1.9.3版本2012年11月2日JI):
[1, 2, 3, 4].shuffle(random: Random.new(0)) # => [1, 3, 2, 4]
[1, 2, 3, 4].shuffle(random: Random.new(0)) # => [1, 3, 2, 4]
順便提及,JRuby的1.7.1使用相同的隨機數發生器作爲MRI 1.9.3p327,但是這是偶然的,不保證。
爲了實現貫穿貫徹執行的確定性洗牌,我想將一個自定義的隨機數發生器傳遞到Array#shuffle
。我認爲這將是微不足道的,但事實證明這是相當複雜的。
這是我第一次嘗試,在MRI:
class NotRandom; end
[1, 2, 3, 4].shuffle(random: NotRandom.new) # => [4, 3, 2, 1]
[1, 2, 3, 4].shuffle(random: NotRandom.new) # => [4, 2, 1, 3]
我預期NoMethodError
告訴我,我需要實現的接口。
任何見解?
UPDATE:
作爲@glebm指出的,NotRandom
繼承Kernel#rand
,這是所需要的接口。這很容易解決,但不幸的是不提供解決方案。
class NotRandom
def rand(*args)
0
end
end
在RBX:
[1, 2, 3, 4].shuffle(random: NotRandom.new) # => [1, 2, 3, 4]
在MRI:
[1, 2, 3, 4].shuffle(random: NotRandom.new) # => [2, 3, 4, 1]
如果從'BasicObject'(而不是默認的'Object')繼承'NotRandom',會發生什麼? – glebm
@glebm這會導致NoMethodError! –
爲什麼你想要一個確定性的洗牌,以及一個確定性洗牌如何不同於一個簡單的有線硬連線列表? –