从Ruby中的列表中删除/删除备用号码

Sam*_*Sam 4 ruby

我有一个问题陈述,即在10人的情况下,椅子排成一个圆圈.有一种跳过一个人并要求下一个人离开的模式(从列表中的第一个人开始).比方说,10人在圈编号1到10的人被要求按顺序离开1,3,5,7,9,2,6,108.所以,人4是胜利者.

获得预期结果的方法是什么?我尝试使用10个元素的数组和这样的编程,

arr = [1,2,3,4,5,6,7,8,9,10]
Run Code Online (Sandbox Code Playgroud)

arr = arr.each_slice(2).map(&:second)

并再次对返回的结果做同样的事情,直到我得到一个元素,但我没有得到预期的结果.例如;

arr.each_slice(2).map(&:second)
=> [2, 4, 6, 8, 10]
[2, 4, 6, 8, 10].each_slice(2).map(&:second)
=> [4, 8, nil]
[4, 8, nil].each_slice(2).map(&:second)
=>[8, nil]
Run Code Online (Sandbox Code Playgroud)

在这种情况下,输出是但我期待4.是否有一些更简单的方法来做到这一点,并获得所需的输出?

Tom*_*ord 8

只有arr.size2的幂才能使用您的解决方案.例如,在第二步中,您将得到:

[2, 4, 6, 8, 10].each_slice(2).to_a #=> [[2, 4], [6, 8], [10]]
Run Code Online (Sandbox Code Playgroud)

这是nil来自:因为[10].second == nil.

而且,逻辑是有缺陷的:在循环的下一次迭代中,它是第二个需要离开的人,而不是第一个.

你需要做的是跟踪"下一个人应该离开吗?" 作为数组索引的单独关注点.

这是一个可能的解决方案:

arr = [1,2,3,4,5,6,7,8,9,10]
should_delete = [true, false].cycle
while(arr.size > 1)
  arr.delete_if { should_delete.next }
end

p arr #=> [4]
Run Code Online (Sandbox Code Playgroud)

[true, false].cycle创建一个无限的枚举器[true, false, true, false, true, .....].因此,当我们遍历数组时,我们会跟踪下一个人是否必须离开此变量.


旁注:这是一个着名的谜题,称为约瑟夫斯问题.我推荐这个视频作为一个很好的解释.你可以通过一个简单的公式确定"胜利者",而不是像这样循环遍历数组!

  • Mindblowing!对于普查员来说真是太棒了! (2认同)

Kim*_*hto 6

当椅子排成一个圆圈时,您可以执行以下操作:

  • 拿起列表中的第一把椅子扔掉
  • 旋转圆圈(将第一把椅子移动到列表的末尾,基本上是跳过它)
  • 重复,直到只剩下一个座位

在代码中:

arr = [1,2,3,4,5,6,7,8,9,10]

until arr.size == 1
  arr.delete_at(0)
  arr.rotate!
end
Run Code Online (Sandbox Code Playgroud)

  • @SagarPandya是的,我在那里有它,但认为`delete_at(0)`在句法上更正确 (2认同)