Find all words from a list of letters, including duplicate letters?

Question:

I am trying to write a Python script that more or less mimics the New York Times game Spelling Bee (if you’ve played it). I have a code that prints out all the words from a list of letters, but I want to be able to repeat letters. For example, fsde produces nothing, but I want feed to be part of the results. Another example is the letters etmxr to produce extreme (Basically any letter can be repeated as many times as possible if the language has a word that allows it). Here is the code I have using itertools so far:

import itertools
import enchant

d = enchant.Dict("en_US")
answer = []

user_input = input("Input letters here: ")
center = input("Input center letter here: ")

while len(center)>1 or center not in user_input:
    center = input("Either you entered a letter not in the first input, or you entered more than one letter. Try again: ")

letters = [x.lower() for x in user_input]

words = d
for t in range(4, len(user_input)):
    for m in itertools.permutations(user_input, t):
        a = "".join(m)
        if center in a:
            if d.check(a):
                answer.append(a)

print(answer)

Right now you just enter letters and get all the words from them, and that’s all I want right now. If there’s any way to get a double or triple letter I would really appreciate it.

I have scoured google and stackoverflow to no avail, I got the original code from a video but it doesn’t have repeated letters and even though I now fully understand permutations I can’t get multiple letters haha. I’ve tried product and combination with no luck, and a lot more but I think it’s just a methodology thing I have wrong.

Asked By: tlars25

||

Answers:

Looks like you don’t need any combinatorics for this, just a simple set comparison:

letters = 'etmxr'

with open('/usr/share/dict/words') as fp:
    for word in fp:
        if set(word.strip()).issubset(letters):
            print(word, end='')

result:

e
eer
em
eme
emeer
emmer
emmet
er
ere
err
ex
exert
exter
extreme
m
me
meet
meeter
...etc
Answered By: gog

I’m not familiar with the enchant module, but if you can iterate over all the words in the dictionary this should work:

user_letter_set = set(user_input)
valid_words = [word for word in d if user_letter_set >= set(word)]

The set comparison operator >= checks if set(word) is a subset of user_letter_set. Or in other words, if user_letter_set contains each type of letter found in set(word).

Answered By: qwatry

Here is another way with sets:

words={}
with open('/usr/share/dict/words') as wf:
    for w in wf:
        w=w.lower().rstrip()
        key=frozenset(w)
        words.setdefault(key, set()).add(w)
    
tgt=frozenset('etmxr')
for fs in words:
    if fs<=tgt:
        k=''.join(sorted(fs))
        print(f""{k}"=>{words[fs]}")

Prints:

"e"=>{'e'}
"er"=>{'eer', 'er', 're', 'reree', 'ree', 'ere', 'err'}
"em"=>{'emm', 'me', 'em', 'eme', 'mem'}
"emr"=>{'reem', 'mer', 'emmer', 'emeer', 'mere'}
"emt"=>{'emmet', 'emmett', 'teem', 'mete', 'met', 'meet'}
"ex"=>{'ex'}
"ertx"=>{'exert', 'exter'}
"emrtx"=>{'extreme'}
"m"=>{'m'}
"emrt"=>{'retem', 'meter', 'teemer', 'remeet', 'term', 'meeter', 'metrete', 'termer'}
"mr"=>{'mr'}
"r"=>{'r'}
"ert"=>{'teeterer', 'tree', 'retree', 'tret', 'teerer', 'teeter', 'ret', 'terret', 'reet', 'terete', 'tetter', 'retter', 'teer'}
"emrx"=>{'remex'}
"erx"=>{'rex'}
"t"=>{'t'}
"et"=>{'tete', 'teet', 'tee', 'te'}
"etx"=>{'text'}
"x"=>{'x'}
Answered By: dawg
Categories: questions Tags: , , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.