在Python 2.7中从列表中删除每个第n个元素

6
我被交付了一个任务,需要为其创建一段代码。 任务如下:
你是一艘帆船的船长,你和你的船员被海盗抓了起来。 那个海盗船长让你们站在他的船甲板上围成一个圆圈,试图决定你们应该以什么顺序走上木板。最终,他决定采用以下方法:
(a) 海盗船长要求你选择一个数字N。
(b) 第一个走上木板的人将是第N个人(从你开始)。
(c) 船长将继续沿着圆圈迫使每个第N个人走上木板。
(d) 当只剩下一个人时,那个人将获得自由。
例如:船员包括:Andrew, Brenda, Craig, Deidre, Edward, Felicity, Greg 和 Harriet。 Andrew选择N=2。船员将按以下顺序走上木板:Brenda, Deidre, Felicity, Harriet, Craig, Greg, Edward。Andrew将获得自由。
目前我所拥有的代码是:
def survivor(names, step):
    names =  ["Andrew", "Brenda", "Craig", "Deidre", "Edward", "Felicity", "Greg", "Harriet"]
    Next = step - 1
    names.pop(Next)
    print names

这将从列表中删除前n个人,但我不确定如何循环遍历列表以继续删除第n个人。

我需要它,所以假设step = 3,那么我需要删除craig,然后从craig开始计数并删除下一个第三个元素,即felicity,依此类推,直到只剩下一个人。

我该怎么做?


那么做出选择的人总是在列表中排名第一吗? - Lev Levitsky
我已经使用了自己的代码来完成第一部分,代码如下:Next = step - 1 while len(names) > 1: names.pop(Next) Next = Next + step Next = (Next - 1) % len(names) print names return names[0]。这段代码可以返回幸存者的名字,但是当我尝试实现建议的第二部分时,它似乎不起作用。我尝试使用以下代码:assert name in names for step in survivor(names, step): if survivor == name: 但是它并没有起作用,而是显示了UnboundLocalError: local variable 'step' referenced before assignment。最终返回的结果应该是step。 - user1839493
2个回答

6
这似乎有效:
from collections import deque
def survivor(names, step):     
    circle = deque(names)
    while len(circle) > 1:
        circle.rotate(1-step)
        print circle.popleft()
    return circle[0]

它会打印出海盗的受害者姓名,并返回幸存者的姓名:
In [17]: crew = ["Andrew", "Brenda", "Craig", "Deidre",
   ....: "Edward", "Felicity", "Greg", "Harriet"]

In [18]: survivor(crew, 2)
Brenda
Deidre
Felicity
Harriet
Craig
Greg
Edward
Out[18]: 'Andrew'

In [19]: survivor(crew, 3)
Craig
Felicity
Andrew
Edward
Brenda
Harriet
Deidre
Out[19]: 'Greg'

谢谢你,Lev。这个完美地解决了我的问题。你不知道我有多感激,我已经卡在这里很久了。非常感谢! - user1839493
@user1839493 只有在你理解它的工作原理而不是仅仅把它交给老师时,它才会有所帮助(如果我猜错了,请原谅)。此外,如果它解决了你的问题,你可以将答案标记为已接受 - Lev Levitsky
你能解释一下deque部分吗? - user1839493
@user1839493 collections.deque 是我在这种情况下用来实现“圆形”的对象。它很像一个列表,但可以从两端轻松访问,并且具有 rotate 方法。请查看我链接的文档页面以了解 rotatepopleft 的描述。 - Lev Levitsky
如果可以的话,Lev,你能帮我处理这个问题吗?我需要创建一个名为safeN的函数,它使用循环和上面的函数来查找最小的N,以保存输入的机组成员名称。 - user1839493
2
@user1839493,这绝对是太多的内容要在评论中解决了。我建议你花些时间自己尝试解决。提示:你可以在循环中使用survivor和递增的step,直到结果是所需的名称,然后step的值就是答案。如果你有任何问题,请发布另一个问题。 - Lev Levitsky

1
以下代码应该可以完成您所要求的所有内容,包括实现 safeN 函数:
import collections
import itertools

def walk_plank(names, N):
    "Walk everyone down the plank."
    circle = collections.deque(names)
    while circle:
        circle.rotate(-N)
        yield circle.pop()

def save_last(names, N):
    "Save the last person from walking the plank."
    for name in walk_plank(names, N):
        pass
    return name

def safeN(names, name):
    "Find the best N to save someone from walking the plank."
    assert name in names, 'Name must be in names!'
    for N in itertools.count(1):
        if save_last(names, N) == name:
            return N

编辑:这里是使用上面代码在Windows中与IDLE一起工作的一些示例用法。

Python 3.3.0 (v3.3.0:bd8afb90ebf2, Sep 29 2012, 10:55:48) [MSC v.1600 32 bit (Intel)] on win32
Type "copyright", "credits" or "license()" for more information.
>>> import collections, itertools
>>> def walk_plank(names, N):
        "Walk everyone down the plank."
        circle = collections.deque(names)
        while circle:
            circle.rotate(-N)
            yield circle.pop()

>>> def save_last(names, N):
        "Save the last person from walking the plank."
        for name in walk_plank(names, N):
            pass
        return name

>>> def safeN(names, name):
        "Find the best N to save someone from walking the plank."
        assert name in names, 'Name must be in names!'
        for N in itertools.count(1):
            if save_last(names, N) == name:
                return N

>>> names = 'Andrew Brenda Craig Deidre Edward Felicity Greg Harriet'.split()
>>> tuple(walk_plank(names, 2))
('Brenda', 'Deidre', 'Felicity', 'Harriet', 'Craig', 'Greg', 'Edward', 'Andrew')
>>> save_last(names, 2)
'Andrew'
>>> safeN(names, 'Andrew')
2
>>> safeN(names, 'Brenda')
19
>>> save_last(names, 19)
'Brenda'
>>> tuple(walk_plank(names, 19))
('Craig', 'Harriet', 'Andrew', 'Felicity', 'Deidre', 'Edward', 'Greg', 'Brenda')
>>> 

谢谢您的帮助,Noctis Skytower。我现在可以实现任务的第二部分了。 - user1839493
我在第一部分中使用了自己的代码,如下所示: Next = step - 1 while len(names) > 1: names.pop(Next) Next = Next + step Next = (Next - 1) % len(names) print namesreturn names[0]这段代码可以返回幸存者,但是当我尝试实现建议的第二部分时,似乎无法正常工作。 - user1839493
我尝试使用以下代码: assert name in names for step in survivor(names, step): if survivor == name: 但它不起作用,显示UnboundLocalError: local variable 'step' referenced before assignment return step - user1839493
@user1839493:请确保使用Python 3.3来运行代码。将会给出代码使用的示例。 - Noctis Skytower

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接