1

这是问题

随机播放。既然您已经完成了新的排序算法,那么相反呢?编写一个 shuffle 方法,该方法接受一个数组并返回一个完全打乱的版​​本。和往常一样,你会想测试它,但测试这个比较棘手:你如何测试以确保你得到一个完美的洗牌?你甚至会说完美的洗牌会是什么?现在测试一下。

这是我的代码答案:

def shuffle arr
    x = arr.length
while x != 0
        new_arr = []
    rand_arr = (rand(x))
    x--
    new_arr.push rand_arr
    arr.pop rand_arr
end

new_arr

end

puts (shuffle ([1,2,3]))

我的错误是什么?为什么这段代码不起作用?

4

6 回答 6

2

这是一个更加 Rubyish 的版本:

class Array
  def shuffle!
    size.downto(1) { |n| push delete_at(rand(n)) }
    self
  end
end

puts [1,2,3].shuffle!
于 2010-11-12T13:08:19.310 回答
2

这是一种更简洁的写法:

def shuffle(arr)
  new_arr = []

  while (arr.any?) do 
    new_arr << arr.delete_at(rand(arr.length))
  end

  new_arr
end

还有一些测试:

5.times do
  puts shuffle((1..5).to_a).join(',')
end

>> 4,2,1,3,5
>> 3,2,1,4,5
>> 4,2,5,1,3
>> 5,2,1,4,3
>> 4,3,1,5,2
于 2010-11-12T16:04:36.730 回答
1

你把你的索引和你的价值观混在一起了。当你这样做的时候new_arr.push rand_arr,你把你想出的任何随机索引作为一个值放在new_arr. 你的意思是new_arr.push arr[rand_arr],索引中arr[rand_arr]的值在哪里。rand_arrarr

于 2010-11-12T10:19:27.217 回答
1

除了其他小错误之外,您似乎不了解 pop 和 push 正在做什么(从数组末尾获取或添加一些项目)。

您可能正在尝试编写如下所示的内容。

def shuffle arr
    x = arr.length
    new_arr = []
    while x != 0
        randpos = rand(x)
        x = x-1
        item = arr[randpos]
        new_arr.push item
        arr[randpos] = arr[x]
        arr.pop
    end

    new_arr

end

puts (shuffle ([1,2,3]))
于 2010-11-12T10:30:50.497 回答
0

Ruby 1.8.7 和 1.9.2 有一个内置的 Array#shuffle 方法。

于 2010-11-12T19:58:37.813 回答
0

马克托马斯答案的变体。由于删除操作的性能,他的算法对于大数组可能会很慢。

class Array
  def shuffle!
    size.downto(1) do |n|
       index=rand(n)
       # swap elements at index and the end
       self[index], self[size-1] = self[size-1],self[index]
    end
    self
  end
end

puts [1,2,3].shuffle!

这个算法是O(size),而Mark的算法是O(size^2)。在我的电脑上,Mark 的答案需要 400 秒才能在我的机器上随机播放 1,000,000 个元素的数组,而我的方法需要 0.5 秒。

于 2014-04-10T14:28:22.800 回答