From 0bfe0cf4f3802a919239cad520746918ccbdc90b Mon Sep 17 00:00:00 2001 From: adithyagenie Date: Sat, 26 Nov 2022 01:54:29 +0530 Subject: [PATCH] Introducing wordle + its solver --- .gitignore | 3 +- wordle-curses/README.md | 6 + wordle-curses/dictionary.py | 58 + wordle-curses/main_readable.py | 147 ++ wordle-curses/solver.py | 49 + wordle-curses/wordle-solver.py | 51 + wordle-curses/words.txt | 2330 ++++++++++++++++++++++++++++++++ 7 files changed, 2643 insertions(+), 1 deletion(-) create mode 100644 wordle-curses/README.md create mode 100644 wordle-curses/dictionary.py create mode 100644 wordle-curses/main_readable.py create mode 100644 wordle-curses/solver.py create mode 100644 wordle-curses/wordle-solver.py create mode 100644 wordle-curses/words.txt diff --git a/.gitignore b/.gitignore index 1a3f0ca..6ee3481 100644 --- a/.gitignore +++ b/.gitignore @@ -5,4 +5,5 @@ __pycache__ maze/__pycache__ maze/modules/__pycache__ saves -tetris \ No newline at end of file +tetris +wordle-curses/__pycache__ \ No newline at end of file diff --git a/wordle-curses/README.md b/wordle-curses/README.md new file mode 100644 index 0000000..ea8dc54 --- /dev/null +++ b/wordle-curses/README.md @@ -0,0 +1,6 @@ +# wordle-curses +A simple TUI wordle game with curses + +![ezgif-7-16d0fbabbd](https://user-images.githubusercontent.com/30610197/151707991-824e3c54-9b69-449c-bc65-e500345d7877.gif) + +Run `main.py` to play. diff --git a/wordle-curses/dictionary.py b/wordle-curses/dictionary.py new file mode 100644 index 0000000..64da3a1 --- /dev/null +++ b/wordle-curses/dictionary.py @@ -0,0 +1,58 @@ +import curses +import requests +import json + +app_id = "4a8fca56" +app_key = "85885b5929e5b14402e75fcb4898d7f5" +language = "en-us" + +def defnsyn(w): + url = r"https://od-api.oxforddictionaries.com:443/api/v2/entries/" + language + "/" + w.lower() + r=requests.get(url, headers={"app_id": app_id, "app_key": app_key}) + if r.status_code != 200: + return None, None + res = r.json() + s1 = res["results"][0]["lexicalEntries"] + lexicalCategories = [] + synonyms = [] + defn = "" + if len(s1) > 1: + for i in range(len(s1)): + lexicalCategories.append(s1[i]["lexicalCategory"]['id']) + if "verb" in lexicalCategories: + baseindex = s1[lexicalCategories.index("verb")]['entries'][0]['senses'][0] + defn = (baseindex['shortDefinitions'][0]) + if "synonyms" in baseindex: + no = 3 if len(baseindex["synonyms"]) > 3 else len(baseindex["synonyms"]) + while no: + synonyms.append(baseindex["synonyms"][no]["text"]) + no -= 1 + synonyms.reverse() + elif "noun" in lexicalCategories: + baseindex = s1[lexicalCategories.index("noun")]['entries'][0]['senses'][0] + defn = (baseindex['shortDefinitions'][0]) + if "synonyms" in baseindex: + no = 3 if len(baseindex["synonyms"]) > 3 else len(baseindex["synonyms"]) + while no: + synonyms.append(baseindex["synonyms"][no]["text"]) + no -= 1 + synonyms.reverse() + else: + baseindex = s1[0]['entries'][0]['senses'][0] + defn = (baseindex['shortDefinitions'][0]) + if "synonyms" in baseindex: + no = 3 if len(baseindex["synonyms"]) > 3 else len(baseindex["synonyms"]) + while no: + synonyms.append(baseindex["synonyms"][no]["text"]) + no -= 1 + synonyms.reverse() + else: + baseindex = s1[0]['entries'][0]['senses'][0] + defn = (baseindex['shortDefinitions'][0]) + if "synonyms" in baseindex: + no = 3 if len(baseindex["synonyms"]) > 3 else len(baseindex["synonyms"]) + while no: + synonyms.append(baseindex["synonyms"][no]["text"]) + no -= 1 + synonyms.reverse() + return defn, synonyms diff --git a/wordle-curses/main_readable.py b/wordle-curses/main_readable.py new file mode 100644 index 0000000..998671f --- /dev/null +++ b/wordle-curses/main_readable.py @@ -0,0 +1,147 @@ +# A slightly more readable version of wordle-curses + +import curses, random, time +from dictionary import defnsyn + +words = open("words.txt", "r").read().split("\n") +colorPairBindings = {"c": 2, "w": 3, "n": 7, "u": 6} +completionMessages = [ + "", + "Genius!", + "Unbelievable!", + "Splendid!", + "Amazing!", + "Great!", + "Good!" +] + +# Draw one row of the board +# Generates new row + colours alphabets in +def writeWord(s, word, remark, y): + s.addstr(y, 0, "│ │ │ │ │ │\n├─┼─┼─┼─┼─┤") + for i, (letter, color) in enumerate(zip(word, remark)): + s.addstr( + y, + i * 2 + 1, + letter.upper(), + curses.color_pair(colorPairBindings[color]), + ) + +# Score a word +def score(guess, word, alphabet): + res = [" "] * 5 + counts = [0] * 26 + + # First process correct letters + for i, c in enumerate(guess): + if c == word[i]: #checking if guess letter corresponds to letter of the same index in chosen word + charIndex = ord(c) - 97 # 97 corresponds to a - gives alphabet number. (eg. h = 8) + counts[charIndex] += 1 + res[i] = "c" # correct spot + alphabet[charIndex] = "c" + + # Then handle wrong and nonpresent letters + for i, c in enumerate(guess): + if c != word[i]: + charIndex = ord(c) - 97 + counts[charIndex] += 1 + if c in word and word.count(c) >= counts[charIndex]: # if freq of letters in guess lesser than freq in word + res[i] = "w" # wrong spot + if alphabet[charIndex] != "c": + alphabet[charIndex] = "w" + else: + res[i] = "n" # not in word + alphabet[charIndex] = "n" + + return "".join(res), alphabet + +# Render current board +# Updates alphabet use state + renders colours of guesses +def render(s, guesses, alphabet): + s.addstr(0, 0, "=== WORDLE ===", curses.color_pair(2)) + for i, c in enumerate(alphabet): + s.addstr( + 1 + int(i // 7), + (i % 7) * 2, + chr(65 + i), + curses.color_pair(colorPairBindings[c]), + ) + s.addstr(6, 0, "╭─┬─┬─┬─┬─╮") + for i, (w, r) in enumerate(guesses): + writeWord(s, w, r, i * 2 + 7) + s.addstr(len(guesses) * 2 + 10, 0, " ") + +# Accept word from user input +def getWord(s, y): + word = "" + while True: + writeWord(s, word, "u" * len(word), y) # u = default blue colour + k = s.getch() + if k == 8: # backspace + word = word[:-1] + elif k == 27: # esc + exit() + elif chr(k) == "\n" and len(word) == 5: + return word + elif chr(k).isalpha() and len(word) < 5: + word += chr(k) + +# Run one game of Wordle +def run(s): + s.clear() + word = random.choice(words) #chosen word + print("Chosen word: ", word) + defn, synonyms = defnsyn(word) + guesses = [] # stores each guess and its result + alphabet = ["u"] * 26 # current status of each letter whether used or not + # c = correct positon, w = correct letter but not position, n = wrong letter, u = not used + # "ccccc" means all letters are in correct spot + while not (len(guesses)) or (guesses[-1][1] != "ccccc" and len(guesses) < 6): + render(s, guesses, alphabet) # Update current state of board from start + guess = getWord(s, len(guesses) * 2 + 7).lower() + if not (guess in words): # Check if given word is valid + s.addstr(len(guesses) * 2 + 10, 0, "INVALID WORD", curses.color_pair(1)) + s.refresh() + time.sleep(1) + continue + res, alphabet = score(guess, word, alphabet) + guesses.append([guess, res]) + render(s, guesses, alphabet) #Renders final board + + # Ending spiel + s.addstr(len(guesses) * 2 + 6, 0, "╰─┴─┴─┴─┴─╯") + if guesses[-1][1] != "ccccc": + s.addstr(len(guesses) * 2 + 8, 0, "No more tries - the word was " + word.upper()) + else: + s.addstr( + len(guesses) * 2 + 8, + 0, + completionMessages[len(guesses)] + ) + if defn and synonyms: + s.addstr(len(guesses) * 2 + 9, 0, word+": ", curses.color_pair(2)) + synonyms = ", ".join(synonyms) + s.addstr(len(guesses) * 2 + 9, 8, defn) + s.addstr(len(guesses) * 2 + 10, 0, "Some synonyms: ", curses.color_pair(2)) + s.addstr(len(guesses) * 2 + 10, 16, synonyms) + s.addstr(len(guesses) * 2 + 11, 0, "[esc] to quit, [enter] to play again", curses.color_pair(3)) + +# Main function +def main(s): + # Initialize colors + for p in [ + (1, curses.COLOR_RED), + (2, curses.COLOR_GREEN), + (3, curses.COLOR_YELLOW), + (7, curses.COLOR_WHITE), + (6, curses.COLOR_CYAN), + ]: + curses.init_pair(p[0], p[1], curses.COLOR_BLACK) + # Run game + while True: + run(s) + if s.getch() == 27: # esc + break + +if __name__ == "__main__": + curses.wrapper(main) \ No newline at end of file diff --git a/wordle-curses/solver.py b/wordle-curses/solver.py new file mode 100644 index 0000000..625a476 --- /dev/null +++ b/wordle-curses/solver.py @@ -0,0 +1,49 @@ +words = open("words.txt").read().split("\n") + +def partition(word, words): + # Get how many words will remain for each possible response + partitions = [] + for a in "MCW": + for b in "MCW": + for c in "MCW": + for d in "MCW": + for e in "MCW": + partitions.append(len(reduce(word, a+b+c+d+e, words))) + return partitions + +def reduce(word, result, words): + # word: 5-letter word (lowercase) + # result: 5-letter str consisting of M, C, W (misplaced, correct, wrong) + res = words[:] + for i, s in enumerate(result): + nres = [] + for w in res: + if s == "M": + if w[i] != word[i] and word[i] in w: nres.append(w) + if s == "C": + if w[i] == word[i]: nres.append(w) + if s == "W": + if w[i] != word[i]: + if not(word[i] in w) or word.count(word[i]) > 1: + nres.append(w) + res = nres + return res + +print("WORDLE SOLVER") +print("=============") +# First guess is precomputed +opt = "crate" +result = "" +while result != "CCCCC": + print(opt) + result = input("> ").upper() + words = reduce(opt, result, words) + opt = "" + opt_size = float("inf") + for word in words: + p = partition(word, words) + avg_partition_size = sum(p)/len(p) + if opt_size > avg_partition_size: + opt_size = avg_partition_size + opt = word + # print(p) \ No newline at end of file diff --git a/wordle-curses/wordle-solver.py b/wordle-curses/wordle-solver.py new file mode 100644 index 0000000..74476da --- /dev/null +++ b/wordle-curses/wordle-solver.py @@ -0,0 +1,51 @@ +words = open("words.txt").read().split() + +guesslist = [] +maxguesses = 6 +wantedletters = [] +uselessletters = [] +correctletters = ["-"] * 5 + +while maxguesses: + try: + correctguess = input("\nEnter correct letter positions (use - for other letters): ").lower() + uselessguess = input("Enter all incorrect letters without space: ").lower() + wantedguess = input("Enter all letters of incorrect postiions: ").lower() + + correctletters = list(correctguess) + for i in uselessguess: + if i not in uselessletters: + uselessletters.append(i) + for i in wantedguess: + if i not in wantedletters: + wantedletters.append(i) + + subsetwanted = [] + for i in words: + if set(wantedletters).issubset(set(i)): + subsetwanted.append(i) + print("First filter", subsetwanted) + for i in uselessletters: + for j in subsetwanted: + if j.count(i): + subsetwanted.remove(j) + + print("Second filter: ", subsetwanted) + + print(correctletters) + temp = [] + for i in range(len(correctletters)): + for j in range(len(subsetwanted)): + if correctletters[i] == "-": + continue + else: + print(i, j, correctletters[i], subsetwanted[j][i]) + if correctletters[i] == subsetwanted[j][i]: + temp.append(subsetwanted[j]) + subsetwanted = temp.copy() + print("Third filter: ", subsetwanted) + + except KeyboardInterrupt: + print("\n\nThe word was found!") + break + maxguesses -= 1 \ No newline at end of file diff --git a/wordle-curses/words.txt b/wordle-curses/words.txt new file mode 100644 index 0000000..ded0ac8 --- /dev/null +++ b/wordle-curses/words.txt @@ -0,0 +1,2330 @@ +aback +abase +abate +abbey +abbot +abhor +abide +abled +abode +abort +about +above +abuse +abyss +acorn +acrid +actor +acute +adage +adapt +adept +admin +admit +adobe +adopt +adore +adorn +adult +affix +afire +afoot +afoul +after +again +agape +agate +agent +agile +aging +aglow +agony +agree +ahead +aider +aisle +alarm +album +alert +algae +alibi +alien +align +alike +alive +allay +alley +allot +allow +alloy +aloft +alone +along +aloof +aloud +alpha +altar +alter +amass +amaze +amber +amble +amend +amiss +amity +among +ample +amply +amuse +angel +anger +angle +angry +angst +anime +ankle +annex +annoy +annul +anode +antic +anvil +aorta +apart +aphid +aping +apnea +apple +apply +apron +aptly +arbor +ardor +arena +argue +arise +armor +aroma +arose +array +arrow +arson +artsy +ascot +ashen +aside +askew +assay +asset +atoll +atone +attic +audio +audit +augur +aunty +avail +avert +avian +avoid +await +awake +award +aware +awash +awful +awoke +axial +axiom +axion +azure +Words +bacon +badge +badly +bagel +baggy +baker +baler +balmy +banal +banjo +barge +baron +basal +basic +basil +basin +basis +baste +batch +bathe +baton +batty +bawdy +bayou +beach +beady +beard +beast +beech +beefy +befit +began +begat +beget +begin +begun +being +belch +belie +belle +belly +below +bench +beret +berry +berth +beset +betel +bevel +bezel +bible +bicep +biddy +bigot +bilge +billy +binge +bingo +biome +birch +birth +bison +bitty +black +blade +blame +bland +blank +blare +blast +blaze +bleak +bleat +bleed +bleep +blend +bless +blimp +blind +blink +bliss +blitz +bloat +block +bloke +blond +blood +bloom +blown +bluer +bluff +blunt +blurb +blurt +blush +board +boast +bobby +boney +bongo +bonus +booby +boost +booth +booty +booze +boozy +borax +borne +bosom +bossy +botch +bough +boule +bound +bowel +boxer +brace +braid +brain +brake +brand +brash +brass +brave +bravo +brawl +brawn +bread +break +breed +briar +bribe +brick +bride +brief +brine +bring +brink +briny +brisk +broad +broil +broke +brood +brook +broom +broth +brown +brunt +brush +brute +buddy +budge +buggy +bugle +build +built +bulge +bulky +bully +bunch +bunny +burly +burnt +burst +bused +bushy +butch +butte +buxom +buyer +bylaw +Words +cabal +cabby +cabin +cable +cacao +cache +cacti +caddy +cadet +cagey +cairn +camel +cameo +canal +candy +canny +canoe +canon +caper +caput +carat +cargo +carol +carry +carve +caste +catch +cater +catty +caulk +cause +cavil +cease +cedar +cello +chafe +chaff +chain +chair +chalk +champ +chant +chaos +chard +charm +chart +chase +chasm +cheap +cheat +check +cheek +cheer +chess +chest +chick +chide +chief +child +chili +chill +chime +china +chirp +chock +choir +choke +chord +chore +chose +chuck +chump +chunk +churn +chute +cider +cigar +cinch +circa +civic +civil +clack +claim +clamp +clang +clank +clash +clasp +class +clean +clear +cleat +cleft +clerk +click +cliff +climb +cling +clink +cloak +clock +clone +close +cloth +cloud +clout +clove +clown +cluck +clued +clump +clung +coach +coast +cobra +cocoa +colon +color +comet +comfy +comic +comma +conch +condo +conic +copse +coral +corer +corny +couch +cough +could +count +coupe +court +coven +cover +covet +covey +cower +coyly +crack +craft +cramp +crane +crank +crash +crass +crate +crave +crawl +craze +crazy +creak +cream +credo +creed +creek +creep +creme +crepe +crept +cress +crest +crick +cried +crier +crime +crimp +crisp +croak +crock +crone +crony +crook +cross +croup +crowd +crown +crude +cruel +crumb +crump +crush +crust +crypt +cubic +cumin +curio +curly +curry +curse +curve +curvy +cutie +cyber +cycle +cynic +Words +daddy +daily +dairy +daisy +dally +dance +dandy +datum +daunt +dealt +death +debar +debit +debug +debut +decal +decay +decor +decoy +decry +defer +deign +deity +delay +delta +delve +demon +demur +denim +dense +depot +depth +derby +deter +detox +deuce +devil +diary +dicey +digit +dilly +dimly +diner +dingo +dingy +diode +dirge +dirty +disco +ditch +ditto +ditty +diver +dizzy +dodge +dodgy +dogma +doing +dolly +donor +donut +dopey +doubt +dough +dowdy +dowel +downy +dowry +dozen +draft +drain +drake +drama +drank +drape +drawl +drawn +dread +dream +dress +dried +drier +drift +drill +drink +drive +droit +droll +drone +drool +droop +dross +drove +drown +druid +drunk +dryer +dryly +duchy +dully +dummy +dumpy +dunce +dusky +dusty +dutch +duvet +dwarf +dwell +dwelt +dying +Words +eager +eagle +early +earth +easel +eaten +eater +ebony +eclat +edict +edify +eerie +egret +eight +eject +eking +elate +elbow +elder +elect +elegy +elfin +elide +elite +elope +elude +email +embed +ember +emcee +empty +enact +endow +enema +enemy +enjoy +ennui +ensue +enter +entry +envoy +epoch +epoxy +equal +equip +erase +erect +erode +error +erupt +essay +ester +ether +ethic +ethos +etude +evade +event +every +evict +evoke +exact +exalt +excel +exert +exile +exist +expel +extol +extra +exult +eying +Words +fable +facet +faint +fairy +faith +false +fancy +fanny +farce +fatal +fatty +fault +fauna +favor +feast +fecal +feign +fella +felon +femme +femur +fence +feral +ferry +fetal +fetch +fetid +fetus +fever +fewer +fiber +ficus +field +fiend +fiery +fifth +fifty +fight +filer +filet +filly +filmy +filth +final +finch +finer +first +fishy +fixer +fizzy +fjord +flack +flail +flair +flake +flaky +flame +flank +flare +flash +flask +fleck +fleet +flesh +flick +flier +fling +flint +flirt +float +flock +flood +floor +flora +floss +flour +flout +flown +fluff +fluid +fluke +flume +flung +flunk +flush +flute +flyer +foamy +focal +focus +foggy +foist +folio +folly +foray +force +forge +forgo +forte +forth +forty +forum +found +foyer +frail +frame +frank +fraud +freak +freed +freer +fresh +friar +fried +frill +frisk +fritz +frock +frond +front +frost +froth +frown +froze +fruit +fudge +fugue +fully +fungi +funky +funny +furor +furry +fussy +fuzzy +Words +gaffe +gaily +gamer +gamma +gamut +gassy +gaudy +gauge +gaunt +gauze +gavel +gawky +gayer +gayly +gazer +gecko +geeky +geese +genie +genre +ghost +ghoul +giant +giddy +gipsy +girly +girth +given +giver +glade +gland +glare +glass +glaze +gleam +glean +glide +glint +gloat +globe +gloom +glory +gloss +glove +glyph +gnash +gnome +godly +going +golem +golly +gonad +goner +goody +gooey +goofy +goose +gorge +gouge +gourd +grace +grade +graft +grail +grain +grand +grant +grape +graph +grasp +grass +grate +grave +gravy +graze +great +greed +green +greet +grief +grill +grime +grimy +grind +gripe +groan +groin +groom +grope +gross +group +grout +grove +growl +grown +gruel +gruff +grunt +guard +guava +guess +guest +guide +guild +guile +guilt +guise +gulch +gully +gumbo +gummy +guppy +gusto +gusty +gypsy +Words +habit +hairy +halve +handy +happy +hardy +harem +harpy +harry +harsh +haste +hasty +hatch +hater +haunt +haute +haven +havoc +hazel +heady +heard +heart +heath +heave +heavy +hedge +hefty +heist +helix +hello +hence +heron +hilly +hinge +hippo +hippy +hitch +hoard +hobby +hoist +holly +homer +honey +honor +horde +horny +horse +hotel +hotly +hound +house +hovel +hover +howdy +human +humid +humor +humph +humus +hunch +hunky +hurry +husky +hussy +hutch +hydro +hyena +hymen +hyper +Words +icily +icing +ideal +idiom +idiot +idler +idyll +igloo +iliac +image +imbue +impel +imply +inane +inbox +incur +index +inept +inert +infer +ingot +inlay +inlet +inner +input +inter +intro +ionic +irate +irony +islet +issue +itchy +ivory +Words +jaunt +jazzy +jelly +jerky +jetty +jewel +jiffy +joint +joist +joker +jolly +joust +judge +juice +juicy +jumbo +jumpy +junta +junto +juror +Words +kappa +karma +kayak +kebab +khaki +kinky +kiosk +kitty +knack +knave +knead +kneed +kneel +knelt +knife +knock +knoll +known +koala +krill +Words +label +labor +laden +ladle +lager +lance +lanky +lapel +lapse +large +larva +lasso +latch +later +lathe +latte +laugh +layer +leach +leafy +leaky +leant +leapt +learn +lease +leash +least +leave +ledge +leech +leery +lefty +legal +leggy +lemon +lemur +leper +level +lever +libel +liege +light +liken +lilac +limbo +limit +linen +liner +lingo +lipid +lithe +liver +livid +llama +loamy +loath +lobby +local +locus +lodge +lofty +logic +login +loopy +loose +lorry +loser +louse +lousy +lover +lower +lowly +loyal +lucid +lucky +lumen +lumpy +lunar +lunch +lunge +lupus +lurch +lurid +lusty +lying +lymph +lyric +Words +macaw +macho +macro +madam +madly +mafia +magic +magma +maize +major +maker +mambo +mamma +mammy +manga +mange +mango +mangy +mania +manic +manly +manor +maple +march +marry +marsh +mason +masse +match +matey +mauve +maxim +maybe +mayor +mealy +meant +meaty +mecca +medal +media +medic +melee +melon +mercy +merge +merit +merry +metal +meter +metro +micro +midge +midst +might +milky +mimic +mince +miner +minim +minor +minty +minus +mirth +miser +missy +mocha +modal +model +modem +mogul +moist +molar +moldy +money +month +moody +moose +moral +moron +morph +mossy +motel +motif +motor +motto +moult +mound +mount +mourn +mouse +mouth +mover +movie +mower +mucky +mucus +muddy +mulch +mummy +munch +mural +murky +mushy +music +musky +musty +myrrh +Words +nadir +naive +nanny +nasal +nasty +natal +naval +navel +needy +neigh +nerdy +nerve +never +newer +newly +nicer +niche +niece +night +ninja +ninny +ninth +noble +nobly +noise +noisy +nomad +noose +north +nosey +notch +novel +nudge +nurse +nutty +nylon +nymph +Words +oaken +obese +occur +ocean +octal +octet +odder +oddly +offal +offer +often +olden +older +olive +ombre +omega +onion +onset +opera +opine +opium +optic +orbit +order +organ +other +otter +ought +ounce +outdo +outer +outgo +ovary +ovate +overt +ovine +ovoid +owing +owner +oxide +ozone +Words +paddy +pagan +paint +paler +palsy +panel +panic +pansy +papal +paper +parer +parka +parry +parse +party +pasta +paste +pasty +patch +patio +patsy +patty +pause +payee +payer +peace +peach +pearl +pecan +pedal +penal +pence +penne +penny +perch +peril +perky +pesky +pesto +petal +petty +phase +phone +phony +photo +piano +picky +piece +piety +piggy +pilot +pinch +piney +pinky +pinto +piper +pique +pitch +pithy +pivot +pixel +pixie +pizza +place +plaid +plain +plait +plane +plank +plant +plate +plaza +plead +pleat +plied +plier +pluck +plumb +plume +plump +plunk +plush +poesy +point +poise +poker +polar +polka +polyp +pooch +poppy +porch +poser +posit +posse +pouch +pound +pouty +power +prank +prawn +preen +press +price +prick +pride +pried +prime +primo +print +prior +prism +privy +prize +probe +prone +prong +proof +prose +proud +prove +prowl +proxy +prude +prune +psalm +pubic +pudgy +puffy +pulpy +pulse +punch +pupil +puppy +puree +purer +purge +purse +pushy +putty +pygmy +Words +quack +quail +quake +qualm +quark +quart +quash +quasi +queen +queer +quell +query +quest +queue +quick +quiet +quill +quilt +quirk +quite +quota +quote +quoth +Words +rabbi +rabid +racer +radar +radii +radio +rainy +raise +rajah +rally +ralph +ramen +ranch +randy +range +rapid +rarer +raspy +ratio +ratty +raven +rayon +razor +reach +react +ready +realm +rearm +rebar +rebel +rebus +rebut +recap +recur +recut +reedy +refer +refit +regal +rehab +reign +relax +relay +relic +remit +renal +renew +repay +repel +reply +rerun +reset +resin +retch +retro +retry +reuse +revel +revue +rhino +rhyme +rider +ridge +rifle +right +rigid +rigor +rinse +ripen +riper +risen +riser +risky +rival +river +rivet +roach +roast +robin +robot +rocky +rodeo +roger +rogue +roomy +roost +rotor +rouge +rough +round +rouse +route +rover +rowdy +rower +royal +ruddy +ruder +rugby +ruler +rumba +rumor +rupee +rural +rusty +Words +sadly +safer +saint +salad +sally +salon +salsa +salty +salve +salvo +sandy +saner +sappy +sassy +satin +satyr +sauce +saucy +sauna +saute +savor +savoy +savvy +scald +scale +scalp +scaly +scamp +scant +scare +scarf +scary +scene +scent +scion +scoff +scold +scone +scoop +scope +score +scorn +scour +scout +scowl +scram +scrap +scree +screw +scrub +scrum +scuba +sedan +seedy +segue +seize +semen +sense +sepia +serif +serum +serve +setup +seven +sever +sewer +shack +shade +shady +shaft +shake +shaky +shale +shall +shalt +shame +shank +shape +shard +share +shark +sharp +shave +shawl +shear +sheen +sheep +sheer +sheet +sheik +shelf +shell +shied +shift +shine +shiny +shire +shirk +shirt +shoal +shock +shone +shook +shoot +shore +shorn +short +shout +shove +shown +showy +shrew +shrub +shrug +shuck +shunt +shush +shyly +siege +sieve +sight +sigma +silky +silly +since +sinew +singe +siren +sissy +sixth +sixty +skate +skier +skiff +skill +skimp +skirt +skulk +skull +skunk +slack +slain +slang +slant +slash +slate +sleek +sleep +sleet +slept +slice +slick +slide +slime +slimy +sling +slink +sloop +slope +slosh +sloth +slump +slung +slunk +slurp +slush +slyly +smack +small +smart +smash +smear +smell +smelt +smile +smirk +smite +smith +smock +smoke +smoky +smote +snack +snail +snake +snaky +snare +snarl +sneak +sneer +snide +sniff +snipe +snoop +snore +snort +snout +snowy +snuck +snuff +soapy +sober +soggy +solar +solid +solve +sonar +sonic +sooth +sooty +sorry +sound +south +sower +space +spade +spank +spare +spark +spasm +spawn +speak +spear +speck +speed +spell +spelt +spend +spent +sperm +spice +spicy +spied +spiel +spike +spiky +spill +spilt +spine +spiny +spire +spite +splat +split +spoil +spoke +spoof +spook +spool +spoon +spore +sport +spout +spray +spree +sprig +spunk +spurn +spurt +squad +squat +squib +stack +staff +stage +staid +stain +stair +stake +stale +stalk +stall +stamp +stand +stank +stare +stark +start +stash +state +stave +stead +steak +steal +steam +steed +steel +steep +steer +stein +stern +stick +stiff +still +stilt +sting +stink +stint +stock +stoic +stoke +stole +stomp +stone +stony +stood +stool +stoop +store +stork +storm +story +stout +stove +strap +straw +stray +strip +strut +stuck +study +stuff +stump +stung +stunk +stunt +style +suave +sugar +suing +suite +sulky +sully +sumac +sunny +super +surer +surge +surly +sushi +swami +swamp +swarm +swash +swath +swear +sweat +sweep +sweet +swell +swept +swift +swill +swine +swing +swirl +swish +swoon +swoop +sword +swore +sworn +swung +synod +syrup +Words +tabby +table +taboo +tacit +tacky +taffy +taint +taken +taker +tally +talon +tamer +tango +tangy +taper +tapir +tardy +tarot +taste +tasty +tatty +taunt +tawny +teach +teary +tease +teddy +teeth +tempo +tenet +tenor +tense +tenth +tepee +tepid +terra +terse +testy +thank +theft +their +theme +there +these +theta +thick +thief +thigh +thing +think +third +thong +thorn +those +three +threw +throb +throw +thrum +thumb +thump +thyme +tiara +tibia +tidal +tiger +tight +tilde +timer +timid +tipsy +titan +tithe +title +toast +today +toddy +token +tonal +tonga +tonic +tooth +topaz +topic +torch +torso +torus +total +totem +touch +tough +towel +tower +toxic +toxin +trace +track +tract +trade +trail +train +trait +tramp +trash +trawl +tread +treat +trend +triad +trial +tribe +trice +trick +tried +tripe +trite +troll +troop +trope +trout +trove +truce +truck +truer +truly +trump +trunk +truss +trust +truth +tryst +tubal +tuber +tulip +tulle +tumor +tunic +turbo +tutor +twang +tweak +tweed +tweet +twice +twine +twirl +twist +twixt +tying +Words +udder +ulcer +ultra +umbra +uncle +uncut +under +undid +undue +unfed +unfit +unify +union +unite +unity +unlit +unmet +unset +untie +until +unwed +unzip +upper +upset +urban +urine +usage +usher +using +usual +usurp +utile +utter +Words +vague +valet +valid +valor +value +valve +vapid +vapor +vault +vaunt +vegan +venom +venue +verge +verse +verso +verve +vicar +video +vigil +vigor +villa +vinyl +viola +viper +viral +virus +visit +visor +vista +vital +vivid +vixen +vocal +vodka +vogue +voice +voila +vomit +voter +vouch +vowel +vying +wacky +wafer +wager +wagon +waist +waive +waltz +warty +waste +watch +water +waver +waxen +weary +weave +wedge +weedy +weigh +weird +welch +welsh +whack +whale +wharf +wheat +wheel +whelp +where +which +whiff +while +whine +whiny +whirl +whisk +white +whole +whoop +whose +widen +wider +widow +width +wield +wight +willy +wimpy +wince +winch +windy +wiser +wispy +witch +witty +woken +woman +women +woody +wooer +wooly +woozy +wordy +world +worry +worse +worst +worth +would +wound +woven +wrack +wrath +wreak +wreck +wrest +wring +wrist +write +wrong +wrote +wrung +wryly +yacht +yearn +yeast +yield +young +youth +zebra +zesty +zonal \ No newline at end of file