Implementação cruzada Deterministic Array # shuffle

É possível passar um gerador de números aleatórios paraArray#shuffle isso faz o shuffle determinístico.

Por exemplo, na RM 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]

No entanto, a implementação do gerador de números aleatórios de aleatório não é especificada. Devido a isso, outras implementações do Ruby têm resultados diferentes.

No Rubinius 2.0.0rc1 (versão 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]

Incidentalmente, o jruby-1.7.1 usa o mesmo gerador de números aleatórios que o MRI 1.9.3p327, mas isso é apenas por acaso, não garantido.

Para ter um shuffle determinístico de implementação consistente, gostaria de passar um gerador de números aleatórios personalizado paraArray#shuffle. Eu pensei que isso seria trivial de fazer, mas acaba por ser bastante complicado.

Aqui está o que eu tentei primeiro, em ressonância magnética:

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]

Eu esperava umNoMethodError me dizendo a interface que eu precisava implementar.

Alguma ideia?

ATUALIZAR:

Como @glebm aponta,NotRandom herdadoKernel#rand, que é a interface necessária. Isso é facilmente contornado, mas infelizmente não oferece uma solução.

class NotRandom
  def rand(*args)
    0
  end
end

Na RBX:

[1, 2, 3, 4].shuffle(random: NotRandom.new) # => [1, 2, 3, 4]

Na ressonância magnética:

[1, 2, 3, 4].shuffle(random: NotRandom.new) # => [2, 3, 4, 1]

questionAnswers(1)

yourAnswerToTheQuestion