2009-08-17 6 views
1

Je suis frappé dans un petit code récursif. J'ai une sortie imprimée et ça s'imprime bien mais quand j'essaie de mettre un compteur pour compter mes réponses, ça me donne des erreurs de scooping.python scooping et récursion

total = 0 
def foo(me, t): 
    if t<0: 
     return 
    if t==0: 
     total = total+1 
     return 
    for i in range(1, me+1): 
     total = total+1 
     return foo(i, t-i) 

il est dit variable locale fait référence avant l'affectation, eh bien, je suis en train de se référer au total dans la première ligne .... Ses pas sur les variables globales, j'ai essayé d'utiliser mondiale aussi bien mais en vain.

Ceci est un problème pur scooping, des idées?

+1

-vous dire portée? – Svante

+2

Votre boucle "for" ne s'exécutera qu'une fois dans chaque récursion, et "i" sera toujours 1. – Svante

Répondre

1

Vous avez oublié de vous assurer de définir le total comme global dans votre fonction. Vous avez dit "j'ai essayé d'utiliser le mondial aussi bien mais en vain". mais quand je l'essayer en dessous ne jette aucune erreur:

total = 0 
def foo(me, t): 
    global total 
    if t<0: 
     return 
    if t==0: 
     total = total+1 
     return 
    for i in range(1, me+1): 
     total = total+1 
     return foo(i, t-i) 
+0

il ne lancera pas d'erreur mais la réponse sera incorrecte. par exemple. Si vous essayez foo (99,100), vous obtiendrez 101 qui est incorrect. mais si vous émettez une déclaration et une utilisation totales et que vous lancez l'impression, le nombre de copies correctes sera imprimé. – hasanatkazmi

+0

ce fil pourrait élaborer sur ce que je veux dire: http://mail.python.org/pipermail/python-list/2001-September/104562.html – hasanatkazmi

+2

Votre analyse est incorrecte: 101 est la bonne réponse. Vous en ajoutez un à chaque fois que vous appuyez sur la ligne 7 ou 10; le dernier vous frappez pour t dans [1.100], le premier quand t = 0. "Global" n'est pas le problème. –

2

Comme mentionné par d'autres, vous avez besoin de la déclaration global pour le total. En outre, comme indiqué par Svante, la boucle for est inutile car codée puisque i est toujours 1. Ainsi, avec une version équivalente de votre code:

total = 0 
def foo(me, t): 
    global total 
    if t < 0: 
     return 
    total = total + 1 
    if t == 0: 
     return 
    return foo(1, t-1) 

foo(99, 100) 
print total 

Il devrait être plus facile de voir que foo (99, 100) sera en effet 101 puisque vous comptez essentiellement vers le bas de 100 à 0. Je ne suis pas bien sûr pourquoi pensez-vous autrement?

1

Je suis sûr que vous savez pas vraiment ce que vous essayez de faire ... (au moins si vous dites que l'ajout du mot-clé global donne des résultats incorrects, mais les erreurs) Silences

vous faire besoin de la ligne « total global » si vous allez essayer de faire référence au total (que vous faites)

(qu'attendez-vous lorsque vous exécutez foo (99, 100)?)

peut-être votre limite les conditions sont mauvaises?

parce que les arguments (99, 100)

  1. foo sauter les deux instructions if
  2. boucle
  3. dans la boucle suivante:

    for i in range(1, 100): 
    total += 1 
    return foo(i, 100-i) 

qui est vraiment équivalent à


    else: 
    total += 1 
    return foo(1, 99) 

(comme Svante disait)

en fonction de vos deux si les conditions foo (1,99) va générer correctement au total + = 100

(99 fois il exécutera votre "autre" déclaration portant le total à 100, puis finalement il atteindra t == 0 et exécuter la dernière finale si où elle poussera le total à votre « incorrect » 101)

vous devez également utiliser Elif pour votre second cas

1

En tant que adv générique ice, recursion toujours utiliser des valeurs de retour, et non des variables globales. La récursion a déjà sa propre charge de complexité, l'augmentant avec des effets secondaires et des interfaces pas claires le rendront encore pire.

Vous devriez essayer quelque chose dans les lignes de ce:

def foo(me, t): 
    if t<0: 
     return 0 
    if t==0: 
     return foo(me, t+1) 
    return foo(me-1, t) 
    for i in range(1, me+1): 
     tot = foo(i, t-i) 
    return tot 

Note: ce code est mal, il pas résoudre votre problème et il pas travailler même sur son propre; Je l'ai mis juste pour donner une idée de la manière de concevoir une récursion plus facile à gérer.

0

Merci, merci, Liffredo. J'ai eu tort, je n'ai pas remarqué que je revenais avant d'ajouter des choses, la boucle ne fonctionnait qu'une seule fois, j'ai corrigé le code. Il est comme ceci:

def foo(me, t): 
    if t<0: 
     return 0 
    if t==0: 
     return 1 
    toreturn = 0 
    for i in range(1, me+1): 
     toreturn = toreturn + foo(i, t-i) 
    return toreturn 

Cet extrait est à ce problème à http://projecteuler.net/index.php?section=problems&id=76