2012-11-19 16 views
6

Próbuję zaprogramować standardowy projekt węża, gdzie drużyna A, drużyna B, drużyna C, drużyna C, drużyna B, drużyna A, ad nauseum.zliczanie, a następnie zmniejszanie zakresu w pytonie

Jeśli wybrano numer 13 (lub wybierz liczbę x), jak mogę określić, która drużyna wybierze następną liczbę drużyn.

mam coś takiego:

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 

Mam uczucie jest prostszy, bardziej pythonic co niż tego rozwiązania. Czy ktoś ma ochotę go włamać?

Więc grałem trochę więcej. Szukam zwrotu pojedynczej wartości, a nie najlepszego sposobu, aby policzyć na liście zapętlonej. Odpowiedź dosłownym może być:

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] 

ten tworzy listę [1,2,3,4,4,3,2,1] Figury się indeks (na przykład 13% (4 * 2) = 5), a następnie zwraca wartość indeksu z listy (np. 4). Im dłuższa lista, tym wolniejsza funkcja.

Możemy użyć pewnej logiki, aby wyciąć listę na pół. Jeśli liczymy się (tj (int(x/n) & 1) False), otrzymujemy oczywistą wartość indeksu (x% N), w przeciwnym wypadku możemy odjąć tę wartość od 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] 

Nadal unika listę ogóle jest najszybszym:

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 

I jeśli trzymać listę jako zmienna zamiast jednego tarła:

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)] 
+0

Gdyby zespół liczbę n, a także numer zespołu 1, wybierz dwa razy z rzędu na przełomie? –

+0

tak. Drużyna 1 i drużyna n mają dwie kolejne selekcje na turnie. – Cole

Odpowiedz

7

Dlaczego nie skorzystać itertools cycle funkcję:

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] 

Uwaga: wcześniej miałem odpowiedział jak uruchomić w górę iw dół, co następuje:

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

zamówienie powinno być [1,2,3,4,4,3,2,1,1,1,2, ...] .. więc co jeszcze mogę zrobić z funkcją cyklu? – Cole

+0

@Cole updated ... –

5

Oto generator, który będzie spełniać to, co chcesz.

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] 
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] 
Powiązane problemy