0

I am making an algorithm for hangman that can guess the word quite well, but it's not working exactly as intended. It's supposed to check the specific positions of characters, but it doesn't really work. For example, I'll use the word aardvark. The first letter it guesses correctly is a, and aardvark contains 3 a's, so the algorithm sees this:

aa_ _ _ a _ _

But when I check the possible words, most of them don't look like this, and the algorithm should instantly be able to solve it, as it's the only word that looks like this.

The program has functions to remove words that contain incorrectly guessed letters, and a function to guess the optimal letter. Both of these functions work perfectly.

This is the part of the code that isn't working, and is supposed to check the position of the letters:

def narrowdown(guessedword, possible):
    for i in guessedword:
        if i != "_":
            for j in possible:
                k = list(j)
                if k[guessedword.index(i)] != i:
                    possible.remove(j)

Here, guessedword is a list version of the letters that the guesser can see, and possible is the list of words that the guessed word can be. The "_" are the blank letters that the guesser can't see.

It repeats this function after every time it has guessed a word.

The problem is that it includes words that definitely aren't eligable. For example, I'll use aardvark again.

When the word looks like this: aa_ _ _ a _ _

And the incorrectly guessed letters are e, i, s and u, it still shows these words:

['aardvark', 'aardwolf', 'abnormal', 'adorably', 'advocacy', 'agaragar', 'agronomy', 'anaconda', 'anaphora', 'approach', 'approval', 'arrogant', 'atombomb']

As I said, aardvark is the only word that fills all those criteria, but the algorithm still takes 3 more guesses to find out which word it is.

Anyone have an idea how to fix this?

Boopiester
  • 141
  • 1
  • 10
  • Does this answer your question? [How to remove items from a list while iterating?](https://stackoverflow.com/questions/1207406/how-to-remove-items-from-a-list-while-iterating) – r.ook Jun 01 '20 at 13:21
  • not really. I know how I would create a new list/remove items from a list, but I don't know how I would determine if a character is in the same position in 2 different strings, which is what I am trying to do. For example, if r is the 5th character in 2 different words. – Boopiester Jun 01 '20 at 13:31
  • Nevermind, this did help with the list being inconsistent, and I learned list comprehension, thanks! – Boopiester Jun 01 '20 at 13:57
  • You should be checking the list of possible words first instead of index of each letter. Right now as you iterate through each `possible` item, the first `a` only removes *some* items, because you are removing it within the loop. Next index, even if the first index of `possible` item isn't an `a`, if the second index survives the condition, it stays on. – r.ook Jun 01 '20 at 13:59

1 Answers1

1

Multi-line solution:

def narrowdown(guessedword, possible):
    res = []
    for w in possible:
        if (len(w) == len(guessedword)) and all((c1 == "_") or (c1 == c2) for c1, c2 in zip(guessedword, w)):
            res.append(w)
    return res

words = ['aardvark', 'aardwolf', 'abnormal', 'adorably', 'advocacy', 'agaragar', 'agronomy', 'anaconda', 'anaphora', 'approach', 'approval', 'arrogant', 'atombomb']
mask = "aa___a__"

print(narrowdown(mask, words))

One line solution:

def narrowdown(gw, p):
    return [w for w in p if (len(w) == len(gw)) and all((c1 == "_") or (c1 == c2) for c1, c2 in zip(gw, w))]

words = ['aardvark', 'aardwolf', 'abnormal', 'adorably', 'advocacy', 'agaragar', 'agronomy', 'anaconda', 'anaphora', 'approach', 'approval', 'arrogant', 'atombomb']
mask = "aa___a__"

print(narrowdown(mask, words))
Rufat
  • 536
  • 1
  • 8
  • 25