2013-06-15 9 views
7

Próbuję napisać funkcję rekurencyjną, która drukuje od 0 do n, ale nie mam pojęcia, jak to zrobić. Przypadkowo wykonana z jednego, który drukuje chociaż n 0:funkcja rekursywna python, która drukuje od 0 do n?

def countdown(n): 
    print(n) 
    if n == 0: 
     return 0 
    return countdown(n - 1) 

Nie wiem, czy to pomaga, czy nie, może uda mi się coś zmienić z kodem, aby przejść od 0 do n?

Odpowiedz

6

Prawie got it!oto stała, uproszczona wersja:

def countup(n): 
    if n >= 0: 
     countup(n - 1) 
     print(n) 

Zauważ, że:

  • Nie trzeba powrócić nic z funkcji rekurencyjnej, że tylko drukuje ceni
  • Do drukowania w kolejności rosnącej The print oświadczenie musi być umieszczone po po rekursywnym wywołaniu
  • Rekursja kończy się, gdy n < 0, biorąc pod uwagę, że drukujemy, nie ma już nic do zrobienia terwards i to jest ok, aby powrócić None (wartość domyślna powrót Pythona)

UPDATE

Wydaje się, że pisanie ogon rozwiązanie rekurencyjne jest modne tutaj :) no cóż, tu jest mój strzał w nim , uproszczona i ogon wersja rekurencyjna użytkownika @ AndyHayden pomysł - za pomocą połączenia ogon optymalizacji dekorator recipe:

@tail_call_optimized 
def countup(N, n=0): 
    print(n) 
    if n < N: 
     countup(N, n + 1) 

tak czy inaczej, to działa zgodnie z oczekiwaniami:

countup(5) 
=> 0 
    1 
    2 
    3 
    4 
    5 
+1

Nie wiedziałem o tym dekoratorze, jak wspaniale! –

3

Można wymienić 0 i N, a + z - aby dokonać rekurencyjną funkcję odliczania do rekurencyjnego odliczanie zegara:

def countup(N, n=0): 
    print(n) 
    if n == N: 
     return 
    return countup(N, n + 1) 

i nazywają to następująco:

countup(3) 

@JFSebastian zwraca uwagę, że ten algorytm ma tę zaletę, że jest O (1), a nie O (n), jak omówiono w tym excellent article o różnicy między liniową i iteracyjną rekurencją, jeśli jest używana z dekoratorem @tail_call_optimized.

+0

Whoa, czekaj, co? – Makoto

+0

OP prosi o rekurencyjną funkcję UP? Nie? –

+0

drukowanie od 0 do n ... –

10

Około 99%.

Pomyśl o swojej podstawowej sprawie i rekurencyjnym kroku - kiedy uderzysz 0, co chcesz zrobić? Gdy nadal pracujesz w dół od n, co chcesz zrobić?

Jeśli odwrócisz kolejność drukowania wartości, osiągniesz pożądany wynik.

def countdown(n): 
    if n != 0: 
     countdown(n-1) 
    print(n) 

Powodem tego jest to, że wywołania rekursywne idą na stosie wywołań. Gdy przekierowujesz połączenia na stos, gdy nie ma mowy o skrzynce końcowej, będziesz kontynuował dodawanie kolejnych połączeń, aż dotrzesz do podstawowego przypadku o numerze n == 0, a następnie zaczniesz drukować wyłącznie wartości.

Pozostałe wywołania będą następnie przesyłane do instrukcji drukowania, ponieważ ich wykonanie powróciło do wiersza po warunku.

Więc wywołanie stosu wygląda mniej więcej tak:

countdown(5) 
    countdown(4) 
     countdown(3) 
      countdown(2) 
       countdown(1) 
        countdown(0) 
        print(0) 
       print(1) 
      print(2) 
     print(3) 
    print(4) 
print(5) 
+0

I tak. To drukuje 0 1 2 3 4 5, wszystko w osobnych liniach. Gdyby to było odliczanie, drukowałoby to 5 4 3 2 1 0, w osobnych wierszach. – Makoto

+2

Twoje rozwiązanie wymaga niepotrzebnej pamięci O (n). @Andy Hayden zapewnia sposób na zrobienie tego w pamięci O (1) (wystarczy dodać dekorator tail_call). [Zobacz dwa obrazy w SICP] (http://mitpress.mit.edu/sicp/full-text/sicp/book/node15.html), aby zrozumieć różnicę (Twoja odpowiedź jest pierwszym zdjęciem) – jfs

+1

@JFSebastian I nie widzę, jak rozwiązanie Andy'ego zużywa mniej pamięci. Oba rozwiązania będą używały ramek stosu 'n', ale Andy ma dwie zmienne lokalne na ramkę, a ma tylko jedną. – Aya

Powiązane problemy