Детерминированный массив перекрестных реализаций # shuffle
Можно передать генератор случайных чиселArray#shuffle
это делает тасовку детерминированной.
Например, в МРТ 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]
Тем не менее, реализация генератора случайных чисел Random isn 'т указан. Из-за этого другие реализации 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
, Я думал, что это будет тривиально, но оказывается, что это довольно сложно.
Вот что я попробовал сначала, в МРТ:
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]
В МРТ:
[1, 2, 3, 4].shuffle(random: NotRandom.new) # => [2, 3, 4, 1]