My computer science and programming class using Python has a new problem set that involves programming the game Hangman. Part I of the problem involves creating a helper function that takes 1) the secret word and 2) a list of guesses, and returns either True or False depending on if the word has been guessed. The function structure will look like the following.
def word_guessed(secret_word, guesses): return <True or False>
The argument secret_word is a string containing the word to be guessed, and guesses is a list of the letters guessed by the player. The function is to return True if the player has guessed the word, and False if the player has not guessed the word.
Iterative / Imperative Approach
My initial thought is to loop through the list of letters in the secret word and check if each letter is contained in the list of guesses. If all the letters in the secret word are in the list of guesses, the secret word has been guessed; otherwise, it has not been guessed. The for loop in Python makes this simple and intuitive. The function can look something like this.
def word_guessed(secret_word, guesses): guessed = True for letter in secret_word: if letter not in guesses: guessed = False break return guessed secret_word = 'secret' guesses = ['s', 'e', 'c', 'r', 'e'] print word_guessed(secret_word, guesses) # False
This solution works brilliantly. I loop through each letter in secret_word and test to see if that letter is in guesses. If it isn't, the word has not been guessed and I immediately break out of the for loop and return False. The functions makes a lot of sense to me, and seems like a good solution.
Python Set / Declarative Approach
Another way to think about this problem, however, is to think of sets and subsets. Wikipedia has a great description of sets in terms of mathematics. The question is asking if the letters that make up the secret word are a subset of the guesses. In other words, are the set of letters in the secret word contained in the set of guesses?
I can use sets in Python to solve this problem in a different way.
def word_guessed(secret_word, guesses): secret_word_letters = set(secret_word) return secret_word_letters.issubset(guesses) secret_word = 'secret' guesses = ['s', 'e', 'c', 'r', 'e', 't', 'a', 'z'] print word_guessed(secret_word, guesses) # True
I really like this solution, because it focuses on what I want to happen and not on how to do it. This gets into the declarative vs. imperative style of programming. In the first approach when I was iterating through the list of letters in the secret word, I was telling python step-by-step how to determine if the letters in secret_word were a subset of the guesses ( imperative programming ). In this approach using Python sets, I am telling Python I need to know if the letters in secret_word are a subset of guesses, and Python can use any algorithm it wants ( declarative programming ).
Recursion in Python
I could also tackle this problem using recursion in Python. There are many better examples of recursion, but here is the same iterative / imperative solution done using recursion.
def word_guessed(secret_word, guesses): if len(secret_word) < 1: return True return (secret_word in guesses) and \ word_guessed(secret_word[1:], guesses) secret_word = 'secret' guesses = ['s', 'e', 'c', 'r', 'e', 't'] print word_guessed(secret_word, guesses) # True
I am sure there are other solutions to this problem, but these are the 3 that came to mind. I love the whole imperative vs declarative approach to programming and discovering declarative solutions to problems. Recursive programming is just very cool to me. I embrace it where I can, but would personally avoid it in this case since I think the declarative approach using sets in Python is more meaningful and intuitive. I hope this has been useful, if not entertaining.
There will be other posts about Hangman. This is just the first part of the problem set.