Python, problem returning correct value

Started by
5 comments, last by Zahlman 15 years, 5 months ago
def countErrors(secret, lettersGuessed, errors):

    if lettersGuessed == "":
         errors = errors + 0  
    else:
         subproblem = lettersGuessed[len(lettersGuessed)-1]
         others = lettersGuessed[0:len(lettersGuessed)-1]
         if subproblem in secret:
             errors = errors + 0
         else:
             errors = errors + 1
             print errors, secret, lettersGuessed, others, subproblem
         countErrors(secret, others, errors)
    return errors        
     
        
        

secret = "guinness"
lettersGuessed = "pnitwzg"
errors = 0
x = countErrors(secret, lettersGuessed, errors)
print x
Here's what it outputs: 0 guinness pnitwzg pnitwz g 1 guinness pnitwz pnitw z 2 guinness pnitw pnit w 3 guinness pnit pni t 3 guinness pni pn i 3 guinness pn p n 4 guinness p p 0 I'm pretty new at this, but this just doesn't seem to make any sense. It does exactly what I want it to, except instead of returning 4, it returns 0. The indentations are correct, I assure you, I just can seem to format it correctly here, so sorry about that. [Edited by - Gixugif on November 12, 2008 3:10:56 AM]
Advertisement
You don't assign the result of the recursive function calls anywhere, so the correct value of error only exists as you go deeper into recursion.

BTW, with Python it is mandatory to use code tags, and what's with all the adding 0?
Also you can shorten:
lettersGuessed[len(lettersGuessed)-1] to lettersGuessed[-1]
lettersGuessed[0:len(lettersGuessed)-1] to lettersGuessed[0:-1]
Wow, I knew it'd be something obvious like that. It was bugging the hell out of me. Anyway, thanks for the help.
Surround your code with [code] or [source] tags to preserve the formatting. :)

Visitor already pointed out your problem, but I'd like to make a few more comments: instead of doing a = b[0:len(b)-1], simply do a = b[0:-1]. Negative indexes simply count from the end of a list. Likewise, c[len(c)-1] does the same as c[-1].

Also, errors = errors + 1 is the same as errors += 1 and errors = errors + 0 can simply be left out.


However, there is no need for recursion here. You want to see how many characters that were entered are not in the secret string, right? How about the following:
errors = 0for letter in lettersGuessed:    if letter not in secret:        errors += 1print errors
Create-ivity - a game development blog Mouseover for more information.
Yeah, I changed all that stuff too.

I know there's no need for recursion, I did it without it first, but it's for a class and we were on recursive functions at the time. I would have just asked my professor but I have a desktop and so couldn't take it to office hours, and apparently I couldn't think of using e-mail until right this second.

Thanks for the pointers and stuff.
Pass 1:
- 'errors = errors + 0' obviously doesn't do anything. Note that if blocks do not necessarily require an else; when we want to do something only in what we think of as the "else" case, then we can negate the condition, and do something only in the "if" case.
- Fix the bug by returning the result of the recursive call.
- Fix the subscripts using the techniques others have mentioned.
- Fix error increment to use +=.

def countErrors(secret, lettersGuessed, errors):    if lettersGuessed == "":         return errors    else:         subproblem = lettersGuessed[-1]         others = lettersGuessed[:-1]         if subproblem not in secret:             errors += 1         return countErrors(secret, others, errors)


Pass 2:
- Since 'subproblem' and 'others' are used only once, and those names don't give us much additional information, we can scrap those variables and just use the corresponding expressions in place.
- Instead of passing an error count forward, we can add in the possible error in the current 'subproblem' *after* finding out how many errors are in the rest of the word (recursively). That simplifies the interface. (After all, why would you expect to have to pass 'errors' to something that is supposed to count the errors for you? :) )

def countErrors(secret, lettersGuessed):    if lettersGuessed == "":         return 0    else:         return countErrors(secret, lettersGuessed[:-1]) +          (0 if lettersGuessed[-1] in secret else 1)


Note that the 'x if blah else y' construct requires Python 2.5. It could also be used to fold in the initial check for an empty string :)

Pass 3: Skip all of that, and just do it in a natural Pythonic way:

# Yes, it's really this simpledef countErrors(secret, lettersGuessed):    return len(x for x in lettersGuessed if x not in secret)

This topic is closed to new replies.

Advertisement