Ruby随机地对一个数组进行洗牌,以便没有元素保持其原始位置

时间:2014-07-03 07:54:27

标签: ruby algorithm shuffle

我有一个存储一些名字的数组。每个人都解决了一项任务,然后我想将每个解决方案分配给不同的人进行验证。简而言之,这意味着我需要以一种没有元素保持其原始位置的方式在数组中执行shuffle。我想到的解决方案是在数组中执行shuffle,直到满足第二个条件,这里是代码:

copied = names.dup
loop do
  copied.shuffle!
  valid = true
  (0...copied.size).each do |i|
     if copied[i] == names[i]
       valid = false
       break
     end
  end
  break  if valid
end

puts copied

我仍然觉得这个问题可能有更优化的解决方案。任何人都有更好的主意吗?

4 个答案:

答案 0 :(得分:3)

您尝试做的就是创建{verifier => task_solver} verifier != task_solver的地图。实现这一目标的一个简单方法就是让每个人都验证下一个人的任务:

verifiers = {}
task_solvers.each_with_index do |task_solver, index|
  verifiers[task_solver] = task_solvers[(index + 1) % task_solvers.size]
end

如果你想要更多随机化,你可以使用它,它使用相同的算法,但只是在发生任何事情之前洗牌你的列表:

verifiers = {}
shuffled_task_solvers = task_solvers.shuffle
shuffled_task_solvers.each_with_index do |task_solver, index|
  verifiers[task_solver] = shuffled_task_solvers[(index + 1) % shuffled_task_solvers.size]
end

答案 1 :(得分:2)

你所追求的可能被称为紊乱。看看这里:http://rosettacode.org/wiki/Permutations/Derangements(Ruby中有一个例子)。

答案 2 :(得分:1)

我认为你只需要一次洗牌。之后,如果复制数组中的某些元素位于其原始位置,则可以将其与其中一个邻居交换(很明显,这两个元素的新位置不能与原始位置相同)。

答案 3 :(得分:1)

这是我想出的。我不知道它是否更好:P

list = [1,2,3,4,5,6,7,8]

def jumble (array)
  new  = array.shuffle
  array.each_with_index do |item, index|
    if new[index] == item
      new[index], new[index - 1] = new[index - 1], new[index]
    end
  end
  new
end

new = jumble (list)
puts new.inspect

输出:

[4, 1, 8, 3, 7, 2, 6, 5]