CS 291 Assignment #6

Due Monday, March 20th (by CLASS TIME)
Not accepted late

The Assignment

For your final Haskell assignment you'll implement a program with input and output, at long last, and compile it into a stand-alone application. We'll use Keith Schwarz's evil hangman as our project. It involves interaction with the user and some interesting data processing, and is of the right scope — challenging but not too challenging. Plus it's cool.

Evil Hangman

In normal hangman, one player picks a secret word and the other tries to guess it, one letter at a time. If the "guesser" picks a letter that occurs in the secret word, the opponent reveals the letter's location and play continues. The guesser loses after some number of incorrect guesses. In normal hangman though, the assumption is that the player picking the word plays truthfully — that they select a word and stick with it. In evil hangman, the computer cheats. Instead of picking a single word, it keeps track of all possible words that could be the answer given the play so far. At each guess, it considers how many candidate words contain the letter and how many don't, and goes with the largest of the groups. (Note that there might be more than one group, as the letter can appear in different places in different words.) Keith has a nice writeup here that describes the approach in more detail.

The Details

Tips

Think carefully about the approach you'll use and the data structures it requires before you get too far along on your implementation. When you get a new guess, how will you determine all of the new word families? How will you figure out which words belong in which families? Is it possible for a word to be in more than one word family? You don't really want to create all possible blanked-out word patterns and then go looking for matching words — there are far too many possible patterns to make that workable, and most of them won't correspond to the actual words in the group you're partitioning into families. So what will you do instead? It's possible to implement this assignment using lists of words as your main data structure. I'll give full credit for list-based solutions, but it would be more efficient to use Haskell's Map class (similar to Java's HashMap).

Sample Outputs

The output below shows how the game should work. The ghc --make command compiled the program into a stand-alone executable, which I then ran in the next command. Note that the initial pattern was ----, and that when I guessed an "e" I was told that there weren't any even though the majority of the words contained an "e"! The algorithm decided to stick with the word family corresponding to ---- since it contained the greatest number of words. (The indented output comes from the behind-the-scenes computations as evil hangman considers the possible word families and picks the largest.) Note also that at the end of the game, the algorithm could have been even more diabolical if it had noticed that while the final two word families were of the same size, one of them (-oo-) required more correct guesses from the player than the other (-ood). Keith mentions this as a possible improvement to the game. Feel free to make it even more evil, but I'll happily give full credit if you pick any of the possible word families in the case of a tie. There are some longer sample outputs from games played with the smallDict and mediumDict.
brichards@laptop[74] : ghc --make hangman.hs
[1 of 1] Compiling Main             ( hangman.hs, hangman.o )
Linking hangman ...
brichards@laptop[75] : ./hangman
Word length?  
4
Number of guesses?  
6
You have 6 guesses left.
Letters guessed: ""
Word: ----
Guess a letter: 
e
    ---- matches ["ally","cool","good"]
    -e-- matches ["beta","deal"]
    e--e matches ["else"]
    --e- matches ["flew","ibex"]
    ---e matches ["hope"]
   Using pattern ----, which matches 3 words
Sorry, there are no e's

You have 5 guesses left.
Letters guessed: "e"
Word: ----
Guess a letter: 
o
    ---- matches ["ally"]
    -oo- matches ["cool","good"]
   Using pattern -oo-, which matches 2 words
Good guess!

You have 5 guesses left.
Letters guessed: "eo"
Word: -oo-
Guess a letter: 
d
    -oo- matches ["cool"]
    -ood matches ["good"]
   Using pattern -ood, which matches 1 words
Good guess!

You have 5 guesses left.
Letters guessed: "eod"
Word: -ood
Guess a letter: 
g
    good matches ["good"]
You guessed it!  The word was "good"

Submitting:

To make it easier for me to test your submissions, I'm asking you to submit via Canvas this time around rather than pasting your code into Gradescope. Please submit only your .hs file! If you want full credit, make sure your code is using the mediumDict dictionary when you submit. I will take points off if it's using anything else.


Brad Richards, 2023