Reputation: 45
This is what I have so far, but I'm stuck. I'm using nltk for the word list and trying to find all the words with the letters in "sand". From this list I want to find all the words I can make from the remaining letters.
import nltk.corpus.words.words()
pwordlist = []
for w in wordlist:
if 's' in w:
if 'a' in w:
if 'n' in w:
if 'd' in w:
pwordlist.append(w)
In this case I have to use all the letters to find the words possible. I think this will work for finding the possible words with the remaining letters, but I can't figure out how to remove only 1 instance of the letters in 'sand'.
puzzle_letters = nltk.FreqDist(x)
[w for w in pwordlist if len(w) = len(pwordlist) and nltk.FreqDist(w) = puzzle_letters]
Upvotes: 1
Views: 155
Reputation: 76234
I would separate the logic into four sections:
contains(word, letters)
, which we'll use to detect whether a word contains "sand"subtract(word, letters)
, which we'll use to remove "sand" from the word.get_anagrams(word)
, which finds all of the anagrams of a word.
from collections import Counter
words = ??? #todo: somehow get a list of every English word.
def contains(word, letters):
return not Counter(letters) - Counter(word)
def subtract(word, letters):
remaining = Counter(word) - Counter(letters)
return "".join(remaining.elements())
anagrams = {}
for word in words:
base = "".join(sorted(word))
anagrams.setdefault(base, []).append(word)
def get_anagrams(word):
return anagrams.get("".join(sorted(word)), [])
for word in words:
if contains(word, "sand"):
reduced_word = subtract(word, "sand")
matches = get_anagrams(reduced_word)
if matches:
print word, matches
Running the above code on the Words With Friends dictionary, I get a lot of results, including:
...
cowhands ['chow']
credentials ['reticle', 'tiercel']
cyanids ['icy']
daftness ['efts', 'fest', 'fets']
dahoons ['oho', 'ooh']
daikons ['koi']
daintiness ['seniti']
daintinesses ['sienites']
dalapons ['opal']
dalesman ['alme', 'lame', 'male', 'meal']
...
Upvotes: 3
Reputation: 50220
Let's answer your question instead of spoiling the fun by doing the whole exercise for you: To remove just one instance of the letter, specify a replacement and give a limit to how many times it should apply:
>>> "Frodo".replace("o", "", 1)
'Frdo'
Or if you need to apply a regexp just once (though in this case you don't need a regexp):
>>> import re
>>> re.sub(r"[od]", "", "Frodo", 1)
'Frdo'
Now if you have a string whose letters (s, a, n, d) you want to remove from a word word
, you can simply loop over the string:
>>> for letter in "sand":
word = word.replace(letter, "", word)
I'll leave it to you to embed this in a loop that goes over all words in your wordlist, and to utilize the remaining letters.
Upvotes: 0
Reputation: 28626
Program:
from nltk.corpus import words
from collections import defaultdict
def norm(word):
return ''.join(sorted(word))
completers = defaultdict(list)
for word in words.words():
completers[norm(word + 'sand')].append(word)
for word in words.words():
comps = completers[norm(word)]
if comps:
print(word, comps)
Output:
...
admirableness ['miserable']
adnascent ['enact']
adroitness ['sorite', 'sortie', 'triose']
adscendent ['cedent', 'decent']
adsorption ['portio']
adventuress ['vesture']
adversant ['avert', 'tarve', 'taver', 'trave']
...
Upvotes: 2