2

Array#shuffleシャッフルを決定論的にする乱数ジェネレーターを渡すことができます。

たとえば、MRI1.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]

ただし、Randomの乱数ジェネレーターの実装は指定されていません。このため、Rubyの他の実装では結果が異なります。

Rubinius 2.0.0rc1(1.9.3リリース2012-11-02 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実装する必要のあるインターフェースを教えてくれると期待していました。

洞察はありますか?


アップデート:

@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]
4

1 に答える 1

1

私にとって、解決策は2つの組み合わせでした。

  1. ランダムAPIを理解します。ただrandです。

  2. 異なるRuby実装には一貫性がないため、独自のシャッフルを実装します。

使用しmy_array.sort_by { @random_generator.rand }ました。

于 2012-12-08T04:52:17.177 に答える