Last active
September 17, 2020 04:23
-
-
Save ftrain/2e16deb9f89add31cf853f6e5cb5b801 to your computer and use it in GitHub Desktop.
Spelling Bee solver
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import argparse | |
from math import ceil | |
from more_itertools import powerset | |
from ordered_set import OrderedSet | |
""" | |
$ pip install more_itertools ordered_set | |
$ python spellingbee.py RACFKOT -h | |
usage: spellingbee.py [-h] [--words WORDS] CHARACTERS | |
Look for solutions for Spelling Bee (https://www.nytimes.com/puzzles/spelling-bee) | |
positional arguments: | |
CHARACTERS 7 letters, required letter first, i.e. LWDATOF | |
optional arguments: | |
-h, --help show this help message and exit | |
--words WORDS Path to a file containing words, default is /usr/share/dict/words | |
$ python spellingbee.py RACFKOT | |
AFAR KROC TART CROCK CARROT | |
AFRO OKRA TORT CROOK FACTOR | |
CARA OORT TROT FRACK KARROO | |
CARR RACK ACCRA FROCK ORATOR | |
CART RAFT ACTOR KARAT ROCOCO | |
CORA ROAR AORTA KRAFT TARTAR | |
CORK ROCK ATTAR ROCCO TARTAR | |
FART ROCK CARAT ROTOR ATTRACT | |
FORA ROOF COROT TAROT TRACTOR | |
FORK ROOK CRACK TATAR CATARACT | |
FORT ROOT CRAFT TRACK KRAKATOA | |
FRAT ROOT CRAFT TRACT | |
KARA TARA CROAK ARAFAT | |
KARO TARO CROAT ARARAT | |
""" | |
# turn a list into a list of n lists (useful for printing columns) | |
def chunkdiv(l, n): | |
for i in range(0, n): | |
yield l[i::n] | |
# use powerset to make permutations of a list, keeping things in alph | |
# order | |
def get_powerset(l): | |
chars = list(l) | |
first_char = chars[0] | |
chars.sort() | |
fset = OrderedSet(["".join(x) for x in powerset(chars)]) | |
return fset, first_char | |
# transform all the words in the dictionary so that "DOGGIES" becomes | |
# "DEIGS" and then check if that's in the powerset from get_powerset() | |
def check_words(chars=None, words_file=None): | |
the_words = [] | |
ps, first_char = get_powerset(chars) | |
with open(words_file) as words_file_handle: | |
words = list(words_file_handle) | |
for word in words: | |
uppered = word.upper() | |
trimmed = uppered.rstrip() | |
filtered = [x for x in list(trimmed) if x.isalnum()] | |
filtered.sort() | |
setted = OrderedSet(filtered) | |
key = "".join(setted) | |
if key in ps and len(trimmed) > 3 and first_char in setted: | |
the_words.append(trimmed) | |
# sort normally... | |
the_words.sort() | |
# ...then by length of word | |
lengthed_words = sorted(the_words, key=len) | |
# figure out how many rows we need (we want 5 columns) | |
rows = ceil(len(lengthed_words) / 5) | |
chunked_words = chunkdiv(lengthed_words, rows) | |
return chunked_words | |
def __main__(): | |
parser = argparse.ArgumentParser( | |
description="Look for solutions for Spelling Bee (https://www.nytimes.com/puzzles/spelling-bee)" | |
) | |
parser.add_argument( | |
"txt", | |
metavar="CHARACTERS", | |
type=str, | |
help="7 letters, required letter first, i.e. LWDATOF", | |
) | |
parser.add_argument( | |
"--words", | |
type=str, | |
help="Path to a file containing words, default is /usr/share/dict/words", | |
default="/usr/share/dict/words", | |
) | |
args = parser.parse_args() | |
words = check_words(chars=args.txt, words_file=args.words) | |
for l in words: | |
fmted = ["{:15}".format(w) for w in l] | |
print("".join(fmted)) | |
if __name__ == "__main__": | |
__main__() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment