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 に答える