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

Time:10-28

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.

CodePudding user response:

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

CodePudding user response:

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).

CodePudding user response:

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'}
  • Related