6

我正在尝试编写标准的蛇选秀,其中 A 队选择,B 队,C 队,C 队,B 队,A 队,令人作呕。

如果 13 号选秀权(或 x 号选秀权)刚刚发生,我如何才能确定哪支球队接下来会为 n 支球队选秀。

我有类似的东西:

def slot(n,x):
    direction = 'down' if (int(x/n) & 1) else 'up'
    spot = (x % n) + 1
    slot = spot if direction == 'up' else ((n+1) - spot)
    return slot

我觉得有一个比这个解决方案更简单、更 Python 的东西。有人愿意破解它吗?

所以我又玩了一会儿。我正在寻找单个值的返回,而不是计算循环列表的最佳方法。最直接的答案可能是:

def slot(n, x): # 0.15757 sec for 100,000x 
    number_range = range(1, n+1) + range(n,0, -1)
    index = x % (n*2)
    return number_range[index]

这将创建一个列表 [1,2,3,4,4,3,2,1],计算出索引(例如 13 % (4*2) = 5),然后从列表中返回索引值(例如4)。列表越长,功能越慢。

我们可以使用一些逻辑将列表减半。如果我们向上计数(即(int(x/n) & 1)返回 False),我们会得到明显的索引值 (x % n),否则我们从 n+1 中减去该值:

def slot(n, x): # 0.11982 sec for 100,000x 
    number_range = range(1, n+1) + range(n,0, -1)
    index = ((n-1) - (x % n)) if (int(x/n) & 1) else (x % n)
    return number_range[index]

仍然完全避免列表是最快的:

def slot(n, x): # 0.07275 sec for 100,000x
    spot = (x % n) + 1
    slot = ((n+1) - spot) if (int(x/n) & 1) else spot
    return slot

如果我将列表作为变量而不是产生一个:

number_list = [1,2,3,4,5,6,7,8,9,10,11,12,12,11,10,9,8,7,6,5,4,3,2,1]
def slot(n, x): # 0.03638 sec for 100,000x
    return number_list[x % (n*2)]
4

4 回答 4

8

为什么不使用 itertoolscycle功能:

from itertools import cycle
li = range(1, n+1) + range(n, 0, -1) # e.g. [1, 2, 3, 4, 4, 3, 2, 1]
it = cycle(li)

[next(it) for _ in xrange(10)] # [1, 2, 3, 4, 4, 3, 2, 1, 1, 2]

注:之前我已经回答了如何上下跑,如下:

it = cycle(range(1, n+1) + range(n, 0, -1)) #e.g. [1, 2, 3, 4, 3, 2, 1, 2, 3, ...]
于 2012-11-19T17:33:56.973 回答
7

这是一个可以满足您想要的生成器。

def draft(n):
    while True:
        for i in xrange(1,n+1):
            yield i
        for i in xrange(n,0,-1):
            yield i

>>> d = draft(3)
>>> [d.next() for _ in xrange(12)]
[1, 2, 3, 3, 2, 1, 1, 2, 3, 3, 2, 1]
于 2012-11-19T17:38:13.970 回答
3
from itertools import chain, cycle

def cycle_up_and_down(first, last):
    up = xrange(first, last+1, 1)
    down = xrange(last, first-1, -1)
    return cycle(chain(up, down))

turns = cycle_up_and_down(1, 4)
print [next(turns) for n in xrange(10)] # [1, 2, 3, 4, 4, 3, 2, 1, 1, 2]
于 2012-11-19T17:50:39.133 回答
2

这是一个先加后减的数字列表:

>>> [ -abs(5-i)+5 for i in range(0,10) ]
[0, 1, 2, 3, 4, 5, 4, 3, 2, 1]

写出来:

count_up_to = 5
for i in range( 0, count_up_to*2 ):
  the_number_you_care_about = -abs(count_up_to-i) + count_up_to
  # do stuff with the_number_you_care_about

更容易阅读:

>>> list( range(0,5) ) + list( range( 5, 0, -1 ) )
[0, 1, 2, 3, 4, 5, 4, 3, 2, 1]

写出来:

count_up_to = 5
for i in list( range(0,5) ) + list( range(5, 0, -1) ):
  # i is the number you care about

另一种方式:

from itertools import chain
for i in chain( range(0,5), range(5,0,-1) ):
  # i is the number you care about
于 2018-12-20T20:56:22.020 回答