反转array.shuffle(随机)来获取原始文件?

时间:2015-04-08 18:19:28

标签: ruby

我想知道是否有办法在Ruby上反转函数array.shuffle(random(seed))? 例如:

array = [1, 2, 3, 4, 5]
array.shuffle!(random: Random.new(seed))
# => [5, 3, 2, 1, 4]

可以使用相同的种子获取原始数组吗? 非常感谢

4 个答案:

答案 0 :(得分:5)

基于Kent Dahl's answer,我提出了以下解决方案:

class Array
  def unshuffle(random:)
    transformed_order = (0...length).to_a.shuffle!(random: random)
    sort_by.with_index{|_, i| transformed_order[i]}
  end
end

SEED = 42

# Random array of numbers from 1 to 10
original_array = (1..10).map{ rand 1..10 }

shuffled = original_array.shuffle(random: Random.new(SEED))
unshuffled = shuffled.unshuffle(random: Random.new(SEED))

puts "Original:   #{original_array}"
puts "Shuffled:   #{shuffled}"
puts "Unshuffled: #{unshuffled}"

puts unshuffled == original_array

示例输出:

Original:   [2, 3, 7, 3, 7, 2, 5, 8, 6, 2]
Shuffled:   [6, 3, 2, 2, 8, 7, 2, 7, 3, 5]
Unshuffled: [2, 3, 7, 3, 7, 2, 5, 8, 6, 2]
true

基本上,它通过使用与原始数组混洗的相同种子来重新排序新的排序数组,然后观察排序数组的最终混洗位置并使用该信息来反转原始数组的混乱。

对于不同版本和Ruby实现中shuffle方法和Random类的实现差异,此解决方案应该是健壮的。

答案 1 :(得分:4)

虽然AFAIK没有洗牌方法,但并非不可能。但是,您可能需要深入研究Array #shuffle的实现,这意味着它可能无法在Ruby版本和不同平台上运行。

由于PRNG是确定性的并且你有种子,在另一个具有相同大小和相同种子的数组上运行一个新的shuffle应该给出完全相同的重新排序顺序。

这意味着您可以随机排列索引数组并使用结果反向映射实际值或元素的混乱数组。

答案 2 :(得分:0)

无法恢复原始阵列。如果您已经对已经排序的数组进行了排序,那么可以使用sort将其取回。而且当你使用shuffle时,这意味着你想要改变顺序。如果要使用它,可以在改组之前存储原始数组。

答案 3 :(得分:0)

你无法撤消随机性,但你可以留下一些碎屑来帮助你回到原来的位置:

foo = ('a' .. 'g').to_a
foo.map!.with_index{ |f, i| [f, i] }.shuffle!
foo # => [["g", 6], ["a", 0], ["d", 3], ["f", 5], ["b", 1], ["c", 2], ["e", 4]]

foo.sort_by!{ |f, i| i }.map!{ |f, i| f }
foo # => ["a", "b", "c", "d", "e", "f", "g"]

或者您只需保留原始数组的副本,或者从其副本中复制:

foo = ('a' .. 'g').to_a
bar = foo.shuffle

foo # => ["a", "b", "c", "d", "e", "f", "g"]
bar # => ["b", "c", "d", "f", "a", "g", "e"]

foo.object_id # => 70308031906280
bar.object_id # => 70308031906080

object_id让我们看看数组是否是单独的对象,这很重要,因为Ruby的工作原理。

保持副本:

foo = ('a' .. 'g').to_a
bar = foo.dup
foo.shuffle!
foo # => ["g", "b", "f", "c", "d", "e", "a"]
bar # => ["a", "b", "c", "d", "e", "f", "g"]
foo.object_id # => 70123956309980
bar.object_id # => 70123956307920

foo = bar
foo.object_id # => 70123956307920
bar.object_id # => 70123956307920

或者:

foo = bar.dup
foo.object_id # => 70123960710260
bar.object_id # => 70123956307920