4
\$\begingroup\$

You guess a word, and if its letter(s) is in the same spot as a hidden word's, you add [] around the letter. If it's in the hidden word, but not in the same spot, you add()).

As of now, I have a whole bunch of loops which I find makes the program un-compact. I would love to see some tips on how to shorten this program! Efficiency isn't a problem. I am looking for compactness.

word = list("tiger")
guesses = 0
holder = 1
while holder == 1:
    s = list(input("Please input what you think the word is"))
    while len(s) > 5 or len(s) < 5:
        print("Please guess a five - letter word!")
        s = list(input("Please input what you think the word is"))
    s2 = s
    for i in range (0, len(word)):
        if word[i] == s[i]:
            letter = ("[",s[i],"]")
            lette = "".join(letter)
            s2[i] = letter
    for i in range (0, len(word)):
        for j in range (0, len(word)):
            if s[i] == word[j]:
                letter2 = ("(", s[i],")")
                letter2 ="".join(letter2)
                s2[i] = letter2
    print(s2)
    guesses = guesses +1
    print ("You have used", guesses, "guesses/guess")
    s3 = ["[t]", "[i]", "[g]", "[e]", "[r]"]
    if s2 == s3:
        print("You WIN!")
        holder = 2
\$\endgroup\$
  • \$\begingroup\$ Compactness? Defined as Simplicity? reduction in lines of code? \$\endgroup\$ – James Khoury Feb 4 '14 at 6:35
  • 1
    \$\begingroup\$ Reduction in lines of code. Simplicity is not required, but as a beginner in Python I would like to see some tips I can understand. \$\endgroup\$ – Anonmly Feb 4 '14 at 6:36
2
\$\begingroup\$
def game(word):
    guesses = 0
    while True:
        user_string = prompt("What do you think the word is? ",
                            lambda s: len(s) == len(word),
                            "Please guess a {}-letter word.".format(len(word)))

        if user_string == word:
            print("You WIN!")
            break

        print([handle_letter(user_string, word, i) for i in user_string])

        guesses += 1
        print ("You have guessed {} times.".format(guesses))


def handle_letter(user_string, word, i):
    if user_string[i] == word[i]:
        return "[" + user_string[i] + "]"
    elif user_string[i] in word:
        return "(" + user_string[i] + ")"
    else:
        return user_string[i]


def prompt(statement, condition, warning):
    user_string = input(statement)
    while not condition(user_string):
        print(warning)
        user_string = input(statement)
    return user_string


def main():
    game("tiger")

if __name__ == '__main__':
    main()

Assuming you are familiar with functions, there should be only two things here that stand out as "weird": the lambda and the list comprehension (this line: print([handle_letter(user_string, word, i) for i in user_string])).

lambdas are just anonymous functions, meaning they are functions that don't have name. I could have easily instead written:

def is_correct_length(user_string):
    return len(user_string) == len(word)

and replaced the lambda line with is_correct_length. It's just shorter this way.*

The list comprehension is a huge code-lines win, but I'd rather you just read http://docs.python.org/2/tutorial/datastructures.html#list-comprehensions than me explain it to you.

*Actually this approach would not work because word is not in scope for the sub-function unless you define it inside of game. lambda has the advantage here of having access to all the variables that in the scope of game, including word, which makes life easier.

If you reeeealy wanted to avoid the lambda you could put the definition of is_correct_length indented and inside of the definition of game, but this is probably not a good move stylistically.

It just occurred to me that this is actually MORE lines of code than you originally had, but I'd say it's better code because it's much more modular. The prompt function, for instance, seems ridiculously useful for games like this one and you can use it everywhere.

If you remove the main() and ifmain wrappers and put thing on one line that I have put on two, you could probably make it shorter, though this is usually not a good idea because readability it far more important than lines of code.

(If you really want to make it shorter - no holds barred - you could do this:

print(["[" + user_string[i] + "]" if user_string[i] == word[i] else "(" + user_string[i] + ")" if user_string[i] in word else user_string[i] for i in range(len(user_string))])

Instead of the current line in game and completely remove handle_letter. However, this is much harder to read so I would advise against it.)

\$\endgroup\$
  • 1
    \$\begingroup\$ Besides the lamda which I don't really understand, I can use alot of the stuff you showed me. Thank you. \$\endgroup\$ – Anonmly Feb 4 '14 at 15:42

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.