我有一个问题陈述,即10个人的椅子排成一个圆圈的情况。有一种跳过一个人并要求下一个人离开的模式(从列表中的第一个人开始)。比方说,10人在圈数为1到10的人被要求按此顺序离开1,3,5,7,9,2,6,10
和8
。因此,人4
是赢家。
获得预期结果的方法是什么?我尝试使用10个元素的数组和这样的编程,
arr = [1,2,3,4,5,6,7,8,9,10]
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]
在这种情况下,输出是,但我期待4.是否有一些更简单的方法来做到这一点并获得所需的输出?
答案 0 :(得分:8)
只有当arr.size
是2的幂时,您的解决方案才有效。例如,在第二步中,您将得到:
[2, 4, 6, 8, 10].each_slice(2).to_a #=> [[2, 4], [6, 8], [10]]
这是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]
[true, false].cycle
创建了一个[true, false, true, false, true, .....]
的无限枚举器。因此,当我们遍历数组时,我们会跟踪下一个人是否必须离开此变量。
旁注:这是一个着名的谜题,称为Josephus problem。我推荐this video作为一个很好的解释。你实际上可以确定"胜利者"通过一个简单的公式,而不是像那样循环遍历数组!
答案 1 :(得分:6)
当椅子排成一个圆圈时,您可以执行以下操作:
在代码中:
Error in € (index 9)
答案 2 :(得分:1)
def last_person_standing(arr)
(arr.size-1).times.reduce(arr) { |a,_| a << a.shift(2).last }.first
end
接下来几点。
n
个元素,则会有n-1
个步骤,每个步骤都会删除该数组的一个元素; inject
),无需在末尾添加一行来返回所需的值; arr
变异reduce
替换arr
的参数(arr.dup
); a << a.shift(2).last
删除数组a
的前两个元素,并将第二个元素追加到a
的末尾; .first
添加到操作行的末尾以返回剩余的元素而不是包含该单个元素的数组,因为它似乎更有用;和arr.size < 2
。试试吧。
last_person_standing %w| Agnes Billy-Bob Trixy Bubba Wanda |
#=> "Billy-Bob"
更多示例如下。
(2..10).each do |n|
a = [*1..n]
puts "#{ a }: #{ last_person_standing(a) }"
end
打印
[1, 2]: 2
[1, 2, 3]: 2
[1, 2, 3, 4]: 4
[1, 2, 3, 4, 5]: 2
[1, 2, 3, 4, 5, 6]: 4
[1, 2, 3, 4, 5, 6, 7]: 6
[1, 2, 3, 4, 5, 6, 7, 8]: 8
[1, 2, 3, 4, 5, 6, 7, 8, 9]: 2
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]: 4
这是另一种方式。
def last_person_standing(arr)
while arr.size > 1
odd = arr.size.odd?
arr.pop if odd
arr.delete_if.with_index { |_,i| i.even? }
arr.unshift(nil) if odd
end
arr.first
end
如果在arr
的每轮删除后,如果arr.size
为奇数,则弹出arr
的最后一个元素,删除带有偶数索引的arr
元素然后在unshift
的开头nil
arr
任何占位符对象(我选择了arr.size
)(将在下一个周期删除);如果arr
甚至只是使用偶数索引从"2","1","3","16","8","3","4","1","2"
中删除元素。