Create a gist now

Instantly share code, notes, and snippets.

What would you like to do?
Program to find Shortest Word Ladders
> {-# LANGUAGE BangPatterns #-}
> import Prelude hiding (foldl, foldr, foldl1, foldr1, (.), id)
> import Data.Functor
> import Data.Foldable
> import Data.Traversable
> import Data.Monoid
> import Control.Applicative
> import Control.Monad hiding (mapM, mapM_, forM, forM_)
> import Control.Category
> import Control.Arrow
> import qualified Data.List as L
> import System.Environment
## Finding a Shortest Word Ladder
So, there is a [programming challenge][post] on reddit, to make a program to
find the shortest possible 'word ladder' between two words, given a
limited dictionary of words.
So how might one go about this? Well, first of all, we could obviously
try every possibility of a word ladder between the two words. We will
improve this later, but for now, let's assume we are going to try every
possibility and pick the best. So, finding one possibility, we will need
to be able to find the 'adjacent' words. A word ladder is a set of steps
through different words, where each step changes only one letter, and
each side of the step is a word. So how can we find what steps we can
make from a single word? Well, as all the words we have are 4 letters
long (the list of words is stored at the end of the post), we can cheat
a little. We will use a very loose form of Trie.
> data Trie a = Trie !Bool [Node a] deriving (Show, Eq)
> data Node a = Node !a (Trie a) deriving (Show, Eq)
Don't be worried by the strange pragmas and bangs here - these are just
slight tweaks for performance, and don't actually affect the
functionality. Having defined the data type of our trie, we need to be
able to build one from the word list.
> buildTrie :: (Eq a) => [[a]] -> Trie a
> buildTrie [] = Trie False [] -- The empty tree
> buildTrie xs = Trie hasEmpty steps
> where
> -- Remove any empty items from the list
> (hasEmpty, toAdd) = preFilter xs id
> preFilter [] c = (False, c [])
> preFilter ([]:xs) c = (True, c $ filter (not . null) xs)
> preFilter ( x:xs) c = preFilter xs $ (x:) >>> c
> steps = makeSteps toAdd
> makeSteps [] = []
> makeSteps (x:xs) = Node first next : makeSteps different
> where
> first = head x
> (same, different) = span ((first ==) . head) xs
> next = buildTrie $ fmap tail $ x:same
> wordTrie = buildTrie wordList
Now in order to check that this works, and also to make clearer how the
trie works, we will create a function to read a Trie back into a list.
> foldTrie :: (Eq a) => ([a] -> b -> b) -> b -> Trie a -> b
> foldTrie f = foldTrie' id
> where
> foldTrie' before e (Trie yield children) = if yield then f (before []) m else m
> where
> m = foldDigits' before e children
> foldDigits' _ e [] = e
> foldDigits' before e (x:xs) = foldDigit' before (foldDigits' before e xs) x
> foldDigit' before e (Node c trie) = foldTrie' (before . (c:)) e trie
If you try building a Trie from the wordlist, and then folding over it
using cons and the empty tree to rebuild the list, you should find that
the list you get is equal to the original word list. So we have our trie
structure, now how do we use it to find similar words? Well, we will
define a maximum number of mistakes. Then we move down the tree, and for
each child, either it matches the key, or we use up one of our
mistakes. If we run out of mistakes, we stop traversing the tree in that
branch. First, we define the exact find (as we will use this anyway when
we run out of mistakes).
> findExact :: (Eq a) => [a] -> Trie a -> [[a]]
> findExact k t = replicate (count k 0 t) k
> where
> count [] n (Trie yield _) = if yield then n + 1 else n
> count (x:xs) n (Trie _ children) = foldl' (folder x xs) n children
> folder x xs n (Node c trie) = if x == c then
> count xs n trie
> else
> n
Now, we will perform a similar (in some ways) search, but keeping track
of our mistakes.
> findFuzzy :: (Eq a, Integral n) => n -> [a] -> Trie a -> [[a]]
> findFuzzy = findFuzzy' id []
> where
> findFuzzy' b e 0 k t = (fmap b $ findExact k t) ++ e
> findFuzzy' b e n [] (Trie yield _) = if yield then b [] :e else e
> findFuzzy' b e n (x:xs) (Trie _ children) = foldr (folder b x xs n) e children
> folder b x xs n (Node c trie) e = n' `seq` findFuzzy' (b . (c:)) e n' xs trie
> where
> n' = if x == c then n else n - 1
So, we can now use a fuzzy find routine to find words which we can reach
in one step from our current word. But this isn't really enough on its
own - how do we know which word to go to next? For this, we can bring in
a heuristic search algorithm, which is a way of guessing where on this
massive invisible set of paths we want to go next. The algorithm I am
going to use is called A* search, and it is very simple. We simply visit
the next possibility based on whichever possibility is nearest to the
goal according to a heuristic of the distance. The only requirement on
the heuristic is that it will never over-estimate the distance (i.e. it
returns the minimum possible). So in this case, we can simply return the
number of substitutions we would need, if all possible 4 letter words
were in our word list.
> distance :: (Eq a, Integral n) => [a] -> [a] -> n
> distance l r = distance' l r 0
> where
> distance' [] [] n = n
> distance' (l:ls) (r:rs) n = distance' ls rs $! n'
> where
> n' = if l == r then n else n + 1
Now we need a really quick and dirty priority queue to use to keep track
of the possibilities. I have written this in another file (I say quick
and dirty, it's very mathematically neat, but not very efficient
probably). We can then use this, to find our path from the start word to
the finish word.
> ladders :: (Ord a, Integral n) => Trie a -> [a] -> [a] -> [(n, [[a]])]
> ladders trie from target = consume $ push [(distance from target, 0, [from])] mempty
> where
> consume queue = maybe [] produce $ pop queue
> produce ((_, cost, p@(mid:_)), queue) = if mid == target then
> (cost, p) : consume queue
> else
> consume nextQueue
> where
> nextQueue = push (stepFunc <$> findFuzzy 1 mid trie) queue
> stepFunc step = c `seq` e `seq` (e, c, step:p)
> where
> c = cost + 1
> e = c + distance step target
Wow, that was crazy. But if you try it, you should find it will
work. The consume step merely removes the best possible trail from the
queue, and then the produce step produces the possible further steps, if
any. Producing the further steps is relatively easy - we simply find all
the words that can be reached in one additional step (using the
Trie). Then we just recompose these slightly to add in all the
book-keeping information.
Now, the final step is to write the actual main method to output the
best ladders.
> main = do
> (from:to:_) <- getArgs
> let answers = ladders wordTrie from to
> let best = takeWhile ((==) (fst $ head $ answers) . fst) answers
> forM_ fmap (reverse . snd) best $ \answer -> do
> putStrLn "----------"
> forM_ answer $ show >>> putStrLn
This concludes the main part of this program. What follows are
supporting sections, which are probably not as interesting.
## Extremely Simple Priority Queues
So, we want a really simple version of priority queues. Let's start with
a really simple related structure - an ordered list. We start then, with
a simple newtype alias for a sorted list.
> newtype Ordered a = Ordered { unOrdered :: [a] } deriving (Show, Eq, Ord)
The standard list sort function works brilliantly. It seems a nice idea
to specialise the sort function to return a specifically ordered list.
> sort :: (Ord a) => [a] -> Ordered a
> sort = Ordered . L.sort
We will also want to create single item lists later. These are of course
trivially ordered.
> single :: a -> Ordered a
> single = Ordered . (:[])
And largely for convenience, these lists are foldable like normal.
> instance Foldable Ordered where
> foldl f s = foldl f s . unOrdered
> foldl1 f = foldl1 f . unOrdered
> foldr f e = foldr f e . unOrdered
> foldr1 f = foldr1 f . unOrdered
Then, as these are ordered lists, we should define a special monoid over
them. The normal list monoid is append, but this will not work for
ordered list, as the result is not neccessarily ordered. However, we can
do a classic pairwise merge to join together two ordered lists to make a
new one containing the items from both. It also has an identity (the
empty list as normal), and so is a prime candidate for a monoid.
> instance (Ord a) => Monoid (Ordered a) where
> mempty = Ordered mempty
> mappend l r = Ordered $ unOrdered l `merge` unOrdered r
> -- | Merge two ordered lists, preserving duplicates.
> merge :: (Ord a) => [a] -> [a] -> [a]
> merge [] r = r
> merge l [] = l
> merge ls@(l:lt) rs@(r:rt) = if r < l then r : merge ls rt else l : merge lt rs
However, we don't really want to be merging all the lists all the
time. We can create a structure that allows us to notionally delay
merges so that merges are made, in this case, between lists of hopefully
more similar length. The structure is based on a representation of
binary numbers, using a technique I learned from Chris Okasaki's
fantastic book, [Purely Functional Data Structures][okasaki].
> newtype Merging m = Merging { unMerging :: [Digit m] } deriving (Show, Eq)
> data Digit m = One m | Two m m deriving (Show, Eq)
We need a way of adding another item into this representation (which
will be in this case, another ordered list), which corresponds to
incrementing the number by one.
> cons :: (Monoid m) => m -> Merging m -> Merging m
> cons x = Merging . cons' x . unMerging
> where
> cons' x [] = One x : []
> cons' x ((One r):t) = Two x r : t
> cons' x ((Two l r):t) = One x : cons' (l <> r) t
We will then use a fold across this structure to support adding one
structure to another. This merge monoid which we get very loosely
corresponds to addition, but whereas Okasaki did describe using
functions corresponding to addition quite closely, this is *really*
stretching the analogy.
> instance Foldable Merging where
> foldl f s = foldl folder s . unMerging
> where
> folder s (One l ) = f s l
> folder s (Two l r) = f (f s l) r
> foldr f e = foldr folder e . unMerging
> where
> folder (One l ) e = f l e
> folder (Two l r) e = f l (f r e)
> instance (Monoid m) => Monoid (Merging m) where
> mempty = Merging mempty
> mappend l r = foldr cons r l
Now, having both the ordered list monoid, and the delayed merging
structure, we can define simple priority queues by just combining the
> newtype Queue a = Queue { unQueue :: Merging (Ordered a) }
To add a new set of items onto the queue, we simply sort it and start
merging the oridered list.
> push :: (Ord a) => [a] -> Queue a -> Queue a
> push xs = Queue . cons (sort xs) . unQueue
Popping is slightly more complex. But we simply reduce it to a recursive
solution, where we try popping from the latter parts of the structure,
pop an item from the current part instead if needed, and then rebuild
the entire structure. This means we do more merging than we might want
to, but performance is not too important for this simple task.
> pop :: (Ord a) => Queue a -> Maybe (a, Queue a)
> pop = fmap (second Queue) . foldr popper Nothing . unQueue
> where
> popper (Ordered [] ) t = t
> popper (Ordered xs@(x:xt)) t = case t of
> Nothing -> Just (x, cons (Ordered xt) mempty)
> Just (y, q) -> if y < x then
> Just (y, cons (Ordered xs) q)
> else
> Just (x, cons (single y) $ cons (Ordered xt) q)
And then we simply use the underlying monoid to merge together queues.
> instance (Ord a) => Monoid (Queue a) where
> mempty = Queue mempty
> mappend l r = Queue $ unQueue l <> unQueue r
## The Mighty Word List
Finally, we need the haskell encoding of the huge word list. It's worth
noting that all the words here are of the same length. This meant we
didn't have to worry too much about the length of the keys in our
algorithms. Although it may well have worked anyway, as we did match on
the basis of the length of our keys when searching the trie.
> wordList = [
> "aahs", "aals", "abas", "abba", "abbe", "abed", "abet", "able", "ably", "abos",
> "abut", "abye", "abys", "aced", "aces", "ache", "achy", "acid", "acme", "acne",
> "acre", "acta", "acts", "acyl", "adds", "adit", "ados", "aeon", "aero", "aery",
> "afar", "agar", "agas", "aged", "agee", "ager", "ages", "agha", "agin", "agio",
> "agly", "agma", "agog", "agon", "ague", "ahem", "aide", "aids", "ails", "aims",
> "ains", "airn", "airs", "airt", "airy", "aits", "ajar", "ajee", "akee", "akin",
> "alae", "alan", "alar", "alas", "alba", "albs", "alec", "alee", "alef", "ales",
> "alfa", "alga", "alif", "alit", "alky", "alls", "ally", "alma", "alme", "alms",
> "aloe", "alow", "alps", "also", "alto", "alts", "alum", "amah", "amas", "amen",
> "amia", "amid", "amie", "amin", "amir", "amis", "amps", "amus", "amyl", "anal",
> "anas", "ands", "anes", "anew", "anga", "anil", "anis", "anna", "anoa", "anon",
> "ansa", "anta", "ante", "anti", "ants", "anus", "aped", "aper", "apes", "apex",
> "apod", "arbs", "arch", "arco", "arcs", "area", "ares", "arfs", "aria", "arid",
> "aril", "arks", "arms", "army", "arts", "arty", "arum", "arvo", "aryl", "asea",
> "ashy", "asks", "asps", "atap", "ates", "atma", "atom", "atop", "auks", "aunt",
> "aura", "auto", "aver", "aves", "avid", "avos", "avow", "away", "awed", "awee",
> "awes", "awls", "awns", "awny", "awry", "axal", "axed", "axel", "axes", "axil",
> "axis", "axle", "axon", "ayah", "ayes", "ayin", "azan", "azon", "baal", "baas",
> "baba", "babe", "babu", "baby", "bach", "back", "bade", "bads", "baff", "bags",
> "baht", "bail", "bait", "bake", "bald", "bale", "balk", "ball", "balm", "bals",
> "bams", "band", "bane", "bang", "bani", "bank", "bans", "baps", "barb", "bard",
> "bare", "barf", "bark", "barm", "barn", "bars", "base", "bash", "bask", "bass",
> "bast", "bate", "bath", "bats", "batt", "baud", "bawd", "bawl", "bays", "bead",
> "beak", "beam", "bean", "bear", "beat", "beau", "beck", "beds", "bedu", "beef",
> "been", "beep", "beer", "bees", "beet", "begs", "bell", "bels", "belt", "bema",
> "bend", "bene", "bens", "bent", "berg", "berm", "best", "beta", "beth", "bets",
> "bevy", "beys", "bhut", "bias", "bibb", "bibs", "bice", "bide", "bids", "bier",
> "biff", "bigs", "bike", "bile", "bilk", "bill", "bima", "bind", "bine", "bins",
> "bint", "bios", "bird", "birk", "birl", "birr", "bise", "bisk", "bite", "bits",
> "bitt", "bize", "blab", "blae", "blah", "blam", "blat", "blaw", "bleb", "bled",
> "blet", "blew", "blin", "blip", "blob", "bloc", "blot", "blow", "blub", "blue",
> "blur", "boar", "boas", "boat", "bobs", "bock", "bode", "bods", "body", "boff",
> "bogs", "bogy", "boil", "bola", "bold", "bole", "boll", "bolo", "bolt", "bomb",
> "bond", "bone", "bong", "bonk", "bony", "boob", "book", "boom", "boon", "boor",
> "boos", "boot", "bops", "bora", "bore", "born", "bort", "bosh", "bosk", "boss",
> "bota", "both", "bots", "bott", "bout", "bowl", "bows", "boxy", "boyo", "boys",
> "bozo", "brad", "brae", "brag", "bran", "bras", "brat", "braw", "bray", "bred",
> "bree", "bren", "brew", "brie", "brig", "brim", "brin", "brio", "bris", "brit",
> "broo", "bros", "brow", "brrr", "brut", "bubo", "bubs", "buck", "buds", "buff",
> "bugs", "buhl", "buhr", "bulb", "bulk", "bull", "bumf", "bump", "bums", "bund",
> "bung", "bunk", "bunn", "buns", "bunt", "buoy", "bura", "burd", "burg", "burl",
> "burn", "burp", "burr", "burs", "bury", "bush", "busk", "buss", "bust", "busy",
> "bute", "buts", "butt", "buys", "buzz", "byes", "byre", "byrl", "byte", "cabs",
> "caca", "cade", "cadi", "cads", "cafe", "caff", "cage", "cagy", "caid", "cain",
> "cake", "caky", "calf", "calk", "call", "calm", "calo", "calx", "came", "camp",
> "cams", "cane", "cans", "cant", "cape", "caph", "capo", "caps", "carb", "card",
> "care", "cark", "carl", "carn", "carp", "carr", "cars", "cart", "casa", "case",
> "cash", "cask", "cast", "cate", "cats", "caul", "cave", "cavy", "caws", "cays",
> "ceca", "cede", "cedi", "cees", "ceil", "cell", "cels", "celt", "cent", "cepe",
> "ceps", "cere", "cero", "cess", "cete", "chad", "cham", "chao", "chap", "char",
> "chat", "chaw", "chay", "chef", "chew", "chez", "chia", "chic", "chid", "chin",
> "chip", "chis", "chit", "chon", "chop", "chow", "chub", "chug", "chum", "ciao",
> "cine", "cion", "cire", "cist", "cite", "city", "clad", "clag", "clam", "clan",
> "clap", "claw", "clay", "clef", "clew", "clip", "clod", "clog", "clon", "clop",
> "clot", "cloy", "club", "clue", "coal", "coat", "coax", "cobb", "cobs", "coca",
> "cock", "coco", "coda", "code", "cods", "coed", "coff", "coft", "cogs", "coho",
> "coif", "coil", "coin", "coir", "coke", "cola", "cold", "cole", "cols", "colt",
> "coly", "coma", "comb", "come", "comp", "cone", "coni", "conk", "conn", "cons",
> "cony", "coof", "cook", "cool", "coon", "coop", "coos", "coot", "cope", "cops",
> "copy", "cord", "core", "corf", "cork", "corm", "corn", "cory", "cosh", "coss",
> "cost", "cosy", "cote", "cots", "coup", "cove", "cowl", "cows", "cowy", "coxa",
> "coys", "cozy", "crab", "crag", "cram", "crap", "craw", "crew", "crib", "cris",
> "croc", "crop", "crow", "crud", "crus", "crux", "cube", "cubs", "cuds", "cued",
> "cues", "cuff", "cuif", "cuke", "cull", "culm", "cult", "cunt", "cups", "curb",
> "curd", "cure", "curf", "curl", "curn", "curr", "curs", "curt", "cusk", "cusp",
> "cuss", "cute", "cuts", "cwms", "cyan", "cyma", "cyme", "cyst", "czar", "dabs",
> "dace", "dada", "dado", "dads", "daff", "daft", "dago", "dags", "dahl", "dahs",
> "dais", "daks", "dale", "dals", "dame", "damn", "damp", "dams", "dang", "dank",
> "daps", "darb", "dare", "dark", "darn", "dart", "dash", "data", "date", "dato",
> "daub", "daut", "davy", "dawk", "dawn", "daws", "dawt", "days", "daze", "dead",
> "deaf", "deal", "dean", "dear", "debs", "debt", "deck", "deco", "deed", "deem",
> "deep", "deer", "dees", "deet", "defi", "deft", "defy", "deil", "deke", "dele",
> "delf", "deli", "dell", "dels", "deme", "demo", "demy", "dene", "dens", "dent",
> "deny", "dere", "derm", "desk", "deva", "devs", "dews", "dewy", "dexy", "deys",
> "dhak", "dhal", "dhow", "dial", "dibs", "dice", "dick", "dido", "didy", "died",
> "diel", "dies", "diet", "digs", "dike", "dill", "dime", "dims", "dine", "ding",
> "dink", "dins", "dint", "diol", "dips", "dipt", "dire", "dirk", "dirl", "dirt",
> "disc", "dish", "disk", "diss", "dita", "dite", "dits", "ditz", "diva", "dive",
> "doat", "doby", "dock", "docs", "dodo", "doer", "does", "doff", "doge", "dogs",
> "dogy", "doit", "dojo", "dole", "doll", "dols", "dolt", "dome", "doms", "dona",
> "done", "dong", "dons", "doom", "door", "dopa", "dope", "dopy", "dore", "dork",
> "dorm", "dorp", "dorr", "dors", "dory", "dose", "doss", "dost", "dote", "doth",
> "dots", "doty", "doum", "dour", "doux", "dove", "down", "dows", "doxy", "doze",
> "dozy", "drab", "drag", "dram", "drat", "draw", "dray", "dree", "dreg", "drek",
> "drew", "drib", "drip", "drop", "drub", "drug", "drum", "drys", "duad", "dual",
> "dubs", "duce", "duci", "duck", "duct", "dude", "duds", "duel", "dues", "duet",
> "duff", "dugs", "duit", "duke", "dull", "duly", "duma", "dumb", "dump", "dune",
> "dung", "dunk", "duns", "dunt", "duos", "dupe", "dups", "dura", "dure", "durn",
> "duro", "durr", "dusk", "dust", "duty", "dyad", "dyed", "dyer", "dyes", "dyke",
> "dyne", "each", "earl", "earn", "ears", "ease", "east", "easy", "eath", "eats",
> "eaux", "eave", "ebon", "eche", "echo", "ecus", "eddo", "eddy", "edge", "edgy",
> "edhs", "edit", "eels", "eely", "eery", "effs", "efts", "eger", "eggs", "eggy",
> "egis", "egos", "eide", "eked", "ekes", "elan", "elds", "elks", "ells", "elms",
> "elmy", "else", "emes", "emeu", "emfs", "emic", "emir", "emit", "emus", "ends",
> "engs", "enol", "enow", "eons", "epic", "epos", "eras", "ergo", "ergs", "erne",
> "erns", "eros", "errs", "erst", "eses", "etas", "etch", "eths", "etic", "euro",
> "even", "ever", "eves", "ewer", "ewes", "exec", "exes", "exit", "exon", "eyas",
> "eyed", "eyen", "eyer", "eyes", "eyne", "eyra", "eyre", "eyry", "face", "fact",
> "fade", "fado", "fads", "fags", "fail", "fain", "fair", "fake", "fall", "falx",
> "fame", "fane", "fang", "fano", "fans", "fard", "fare", "farl", "farm", "faro",
> "fart", "fash", "fast", "fate", "fats", "faun", "faux", "fava", "fave", "fawn",
> "fays", "faze", "feal", "fear", "feat", "feck", "feds", "feed", "feel", "fees",
> "feet", "fehs", "fell", "felt", "feme", "fems", "fend", "fens", "feod", "fere",
> "fern", "fess", "feta", "fete", "fets", "feud", "feus", "fiar", "fiat", "fibs",
> "fice", "fico", "fido", "fids", "fief", "fife", "figs", "fila", "file", "fill",
> "film", "filo", "fils", "find", "fine", "fink", "fino", "fins", "fire", "firm",
> "firn", "firs", "fisc", "fish", "fist", "fits", "five", "fixt", "fizz", "flab",
> "flag", "flak", "flam", "flan", "flap", "flat", "flaw", "flax", "flay", "flea",
> "fled", "flee", "flew", "flex", "fley", "flic", "flip", "flit", "floc", "floe",
> "flog", "flop", "flow", "flub", "flue", "flus", "flux", "foal", "foam", "fobs",
> "foci", "foes", "fogs", "fogy", "fohn", "foil", "foin", "fold", "folk", "fond",
> "fons", "font", "food", "fool", "foot", "fops", "fora", "forb", "ford", "fore",
> "fork", "form", "fort", "foss", "foul", "four", "fowl", "foxy", "foys", "fozy",
> "frae", "frag", "frap", "frat", "fray", "free", "fret", "frig", "frit", "friz",
> "froe", "frog", "from", "frow", "frug", "fubs", "fuci", "fuck", "fuds", "fuel",
> "fugs", "fugu", "fuji", "full", "fume", "fumy", "fund", "funk", "funs", "furl",
> "furs", "fury", "fuse", "fuss", "futz", "fuze", "fuzz", "fyce", "fyke", "gabs",
> "gaby", "gadi", "gads", "gaed", "gaen", "gaes", "gaff", "gaga", "gage", "gags",
> "gain", "gait", "gala", "gale", "gall", "gals", "gama", "gamb", "game", "gamp",
> "gams", "gamy", "gane", "gang", "gaol", "gape", "gaps", "gapy", "garb", "gars",
> "gash", "gasp", "gast", "gate", "gats", "gaud", "gaum", "gaun", "gaur", "gave",
> "gawk", "gawp", "gays", "gaze", "gear", "geck", "geds", "geed", "geek", "gees",
> "geez", "geld", "gels", "gelt", "gems", "gene", "gens", "gent", "genu", "germ",
> "gest", "geta", "gets", "geum", "ghat", "ghee", "ghis", "gibe", "gibs", "gids",
> "gied", "gien", "gies", "gift", "giga", "gigs", "gild", "gill", "gilt", "gimp",
> "gink", "gins", "gips", "gird", "girl", "girn", "giro", "girt", "gist", "gits",
> "give", "glad", "gled", "glee", "gleg", "glen", "gley", "glia", "glib", "glim",
> "glob", "glom", "glop", "glow", "glue", "glug", "glum", "glut", "gnar", "gnat",
> "gnaw", "gnus", "goad", "goal", "goas", "goat", "gobo", "gobs", "goby", "gods",
> "goer", "goes", "gogo", "gold", "golf", "gone", "gong", "good", "goof", "gook",
> "goon", "goop", "goos", "gore", "gorp", "gory", "gosh", "gout", "gowd", "gowk",
> "gown", "goys", "grab", "grad", "gram", "gran", "grat", "gray", "gree", "grew",
> "grey", "grid", "grig", "grim", "grin", "grip", "grit", "grog", "grot", "grow",
> "grub", "grue", "grum", "guan", "guar", "guck", "gude", "guff", "guid", "gulf",
> "gull", "gulp", "guls", "gums", "gunk", "guns", "gush", "gust", "guts", "guvs",
> "guys", "gybe", "gyms", "gyps", "gyre", "gyri", "gyro", "gyve", "haaf", "haar",
> "habu", "hack", "hade", "hadj", "haed", "haem", "haen", "haes", "haet", "haft",
> "hags", "haha", "hahs", "haik", "hail", "hair", "haji", "hajj", "hake", "hale",
> "half", "hall", "halm", "halo", "halt", "hame", "hams", "hand", "hang", "hank",
> "hant", "haps", "hard", "hare", "hark", "harl", "harm", "harp", "hart", "hash",
> "hasp", "hast", "hate", "hath", "hats", "haul", "haut", "have", "hawk", "haws",
> "hays", "haze", "hazy", "head", "heal", "heap", "hear", "heat", "hebe", "heck",
> "heed", "heel", "heft", "hehs", "heil", "heir", "held", "hell", "helm", "helo",
> "help", "heme", "hemp", "hems", "hens", "hent", "herb", "herd", "here", "herl",
> "herm", "hern", "hero", "hers", "hest", "heth", "hets", "hewn", "hews", "hick",
> "hide", "hied", "hies", "high", "hike", "hila", "hili", "hill", "hilt", "hind",
> "hins", "hint", "hips", "hire", "hisn", "hiss", "hist", "hits", "hive", "hoar",
> "hoax", "hobo", "hobs", "hock", "hods", "hoed", "hoer", "hoes", "hogg", "hogs",
> "hoke", "hold", "hole", "holk", "holm", "holp", "hols", "holt", "holy", "home",
> "homo", "homy", "hone", "hong", "honk", "hons", "hood", "hoof", "hook", "hoop",
> "hoot", "hope", "hops", "hora", "horn", "hose", "host", "hots", "hour", "hove",
> "howe", "howf", "howk", "howl", "hows", "hoya", "hoys", "hubs", "huck", "hued",
> "hues", "huff", "huge", "hugs", "hula", "hulk", "hull", "hump", "hums", "hung",
> "hunh", "hunk", "huns", "hunt", "hurl", "hurt", "hush", "husk", "huts", "hwan",
> "hyla", "hype", "hypo", "hyps", "hyte", "iamb", "ibex", "ibis", "iced", "ices",
> "ichs", "icky", "idea", "idem", "ides", "idle", "idly", "ikat", "ilea", "ilex",
> "ilia", "ilka", "ilks", "ills", "illy", "imid", "impi", "imps", "inby", "inch",
> "info", "inia", "inks", "inky", "inly", "inns", "inro", "inti", "into", "ions",
> "iota", "ired", "ires", "irid", "iris", "irks", "isle", "itch", "item", "iwis",
> "ixia", "izar", "jabs", "jack", "jade", "jagg", "jags", "jail", "jake", "jamb",
> "jams", "jane", "jape", "jarl", "jars", "jato", "jauk", "jaup", "java", "jaws",
> "jays", "jazz", "jean", "jeed", "jeep", "jeer", "jees", "jeez", "jefe", "jell",
> "jeon", "jerk", "jess", "jest", "jete", "jets", "jews", "jiao", "jibb", "jibe",
> "jibs", "jiff", "jigs", "jill", "jilt", "jimp", "jink", "jinn", "jins", "jinx",
> "jive", "jobs", "jock", "joes", "joey", "jogs", "john", "join", "joke", "joky",
> "jole", "jolt", "josh", "joss", "jota", "jots", "jouk", "jowl", "jows", "joys",
> "juba", "jube", "juga", "jugs", "juke", "jump", "junk", "jupe", "jura", "jury",
> "just", "jute", "juts", "kaas", "kabs", "kadi", "kaes", "kafs", "kaif", "kail",
> "kain", "kaka", "kaki", "kale", "kame", "kami", "kana", "kane", "kaon", "kapa",
> "kaph", "karn", "kart", "kata", "kats", "kava", "kayo", "kays", "kbar", "keas",
> "keck", "keef", "keek", "keel", "keen", "keep", "keet", "kefs", "kegs", "keir",
> "kelp", "kemp", "keno", "kens", "kent", "kepi", "keps", "kept", "kerb", "kerf",
> "kern", "keto", "keys", "khaf", "khan", "khat", "khet", "khis", "kibe", "kick",
> "kids", "kief", "kier", "kifs", "kike", "kill", "kiln", "kilo", "kilt", "kina",
> "kind", "kine", "king", "kink", "kino", "kins", "kips", "kirk", "kirn", "kirs",
> "kiss", "kist", "kite", "kith", "kits", "kiva", "knap", "knar", "knee", "knew",
> "knit", "knob", "knop", "knot", "know", "knur", "koan", "koas", "kobo", "kobs",
> "koel", "kohl", "kola", "kolo", "konk", "kook", "koph", "kops", "kore", "kors",
> "koss", "koto", "kris", "kues", "kvas", "kyak", "kyar", "kyat", "kyte", "labs",
> "lace", "lack", "lacs", "lacy", "lade", "lads", "lady", "lags", "laic", "laid",
> "lain", "lair", "lake", "lakh", "laky", "lall", "lama", "lamb", "lame", "lamp",
> "lams", "land", "lane", "lang", "lank", "laps", "lard", "lari", "lark", "lars",
> "lase", "lash", "lass", "last", "late", "lath", "lati", "lats", "laud", "lava",
> "lave", "lavs", "lawn", "laws", "lays", "laze", "lazy", "lead", "leaf", "leak",
> "leal", "lean", "leap", "lear", "leas", "lech", "leek", "leer", "lees", "leet",
> "left", "legs", "lehr", "leis", "leke", "leks", "leku", "lend", "leno", "lens",
> "lent", "lept", "less", "lest", "lets", "leud", "leva", "levo", "levy", "lewd",
> "leys", "liar", "libs", "lice", "lich", "lick", "lido", "lids", "lied", "lief",
> "lien", "lier", "lies", "lieu", "life", "lift", "like", "lilt", "lily", "lima",
> "limb", "lime", "limn", "limo", "limp", "limy", "line", "ling", "link", "linn",
> "lino", "lins", "lint", "liny", "lion", "lips", "lira", "lire", "liri", "lisp",
> "list", "lite", "lits", "litu", "live", "load", "loaf", "loam", "loan", "lobe",
> "lobo", "lobs", "loca", "loch", "loci", "lock", "loco", "lode", "loft", "loge",
> "logo", "logs", "logy", "loin", "loll", "lone", "long", "loof", "look", "loom",
> "loon", "loop", "loos", "loot", "lope", "lops", "lord", "lore", "lorn", "lory",
> "lose", "loss", "lost", "lota", "loth", "loti", "lots", "loud", "loup", "lour",
> "lout", "love", "lowe", "lown", "lows", "luau", "lube", "luce", "luck", "lude",
> "lues", "luff", "luge", "lugs", "lull", "lulu", "lump", "lums", "luna", "lune",
> "lung", "lunk", "lunt", "luny", "lure", "lurk", "lush", "lust", "lute", "lutz",
> "luvs", "luxe", "lyes", "lyre", "lyse", "maar", "mabe", "mace", "mach", "mack",
> "macs", "made", "mads", "maes", "mage", "magi", "mags", "maid", "mail", "maim",
> "main", "mair", "make", "mako", "male", "mall", "malm", "malt", "mama", "mana",
> "mane", "mano", "mans", "many", "maps", "marc", "mare", "mark", "marl", "mars",
> "mart", "mash", "mask", "mass", "mast", "mate", "math", "mats", "matt", "maud",
> "maul", "maun", "maut", "mawn", "maws", "maxi", "maya", "mayo", "mays", "maze",
> "mazy", "mead", "meal", "mean", "meat", "meed", "meek", "meet", "meld", "mell",
> "mels", "melt", "memo", "mems", "mend", "meno", "menu", "meou", "meow", "mere",
> "merk", "merl", "mesa", "mesh", "mess", "meta", "mete", "meth", "mewl", "mews",
> "meze", "mhos", "mibs", "mica", "mice", "mick", "midi", "mids", "mien", "miff",
> "migg", "migs", "mike", "mild", "mile", "milk", "mill", "milo", "mils", "milt",
> "mime", "mina", "mind", "mine", "mini", "mink", "mint", "minx", "mire", "miri",
> "mirk", "mirs", "miry", "mise", "miso", "miss", "mist", "mite", "mitt", "mity",
> "mixt", "moan", "moas", "moat", "mobs", "mock", "mocs", "mode", "modi", "mods",
> "mogs", "moil", "mojo", "moke", "mola", "mold", "mole", "moll", "mols", "molt",
> "moly", "mome", "momi", "moms", "monk", "mono", "mons", "mony", "mood", "mool",
> "moon", "moor", "moos", "moot", "mope", "mops", "mopy", "mora", "more", "morn",
> "mors", "mort", "mosk", "moss", "most", "mote", "moth", "mots", "mott", "moue",
> "move", "mown", "mows", "moxa", "mozo", "much", "muck", "muds", "muff", "mugg",
> "mugs", "mule", "mull", "mumm", "mump", "mums", "mumu", "muni", "muns", "muon",
> "mura", "mure", "murk", "murr", "muse", "mush", "musk", "muss", "must", "mute",
> "muts", "mutt", "myna", "myth", "nabe", "nabs", "nada", "nags", "naif", "nail",
> "name", "nana", "nans", "naoi", "naos", "nape", "naps", "narc", "nard", "nark",
> "nary", "nave", "navy", "nays", "nazi", "neap", "near", "neat", "nebs", "neck",
> "need", "neem", "neep", "neif", "nema", "nene", "neon", "nerd", "ness", "nest",
> "nets", "nett", "neuk", "neum", "neve", "nevi", "news", "newt", "next", "nibs",
> "nice", "nick", "nide", "nidi", "nigh", "nill", "nils", "nims", "nine", "nipa",
> "nips", "nisi", "nite", "nits", "nixe", "nixy", "nobs", "nock", "node", "nodi",
> "nods", "noel", "noes", "nogg", "nogs", "noil", "noir", "nolo", "noma", "nome",
> "noms", "nona", "none", "nook", "noon", "nope", "nori", "norm", "nose", "nosh",
> "nosy", "nota", "note", "noun", "nous", "nova", "nows", "nowt", "nubs", "nude",
> "nuke", "null", "numb", "nuns", "nurd", "nurl", "nuts", "oafs", "oaks", "oars",
> "oast", "oath", "oats", "obes", "obey", "obia", "obis", "obit", "ocas", "odds",
> "odea", "odes", "odic", "ofay", "offs", "ogee", "ogle", "ogre", "ohed", "ohia",
> "oils", "oily", "oink", "okas", "okay", "okeh", "okes", "okra", "olds", "oldy",
> "olea", "oleo", "oles", "olio", "olla", "omen", "omer", "omit", "ones", "only",
> "onto", "onus", "oohs", "oops", "oots", "ooze", "oozy", "opah", "opal", "oped",
> "open", "opes", "opts", "opus", "orad", "oral", "orbs", "orby", "orca", "orcs",
> "ores", "orgy", "orle", "orra", "orts", "osar", "oses", "otic", "otto", "ouch",
> "ouds", "ouph", "ours", "oust", "outs", "oval", "oven", "over", "owed", "owes",
> "owls", "owns", "oxen", "oxes", "oyer", "oyes", "oyez", "paca", "pace", "pack",
> "pacs", "pact", "padi", "pads", "page", "paid", "paik", "pail", "pain", "pair",
> "pale", "pall", "palm", "palp", "pals", "paly", "pams", "pane", "pang", "pans",
> "pant", "papa", "paps", "para", "pard", "pare", "park", "parr", "pars", "part",
> "pase", "pash", "pass", "past", "pate", "path", "pats", "paty", "pave", "pawl",
> "pawn", "paws", "pays", "peag", "peak", "peal", "pean", "pear", "peas", "peat",
> "pech", "peck", "pecs", "peds", "peed", "peek", "peel", "peen", "peep", "peer",
> "pees", "pegs", "pehs", "pein", "peke", "pele", "pelf", "pelt", "pend", "pens",
> "pent", "peon", "pepo", "peps", "peri", "perk", "perm", "pert", "peso", "pest",
> "pets", "pews", "phat", "phew", "phis", "phiz", "phon", "phot", "phut", "pial",
> "pian", "pias", "pica", "pice", "pick", "pics", "pied", "pier", "pies", "pigs",
> "pika", "pike", "piki", "pile", "pili", "pill", "pily", "pima", "pimp", "pina",
> "pine", "ping", "pink", "pins", "pint", "piny", "pion", "pipe", "pips", "pipy",
> "pirn", "pish", "piso", "piss", "pita", "pith", "pits", "pity", "pixy", "plan",
> "plat", "play", "plea", "pleb", "pled", "plew", "plod", "plop", "plot", "plow",
> "ploy", "plug", "plum", "plus", "pock", "poco", "pods", "poem", "poet", "pogy",
> "pois", "poke", "poky", "pole", "poll", "polo", "pols", "poly", "pome", "pomp",
> "poms", "pond", "pone", "pong", "pons", "pony", "pood", "poof", "pooh", "pool",
> "poon", "poop", "poor", "pope", "pops", "pore", "pork", "porn", "port", "pose",
> "posh", "post", "posy", "pots", "pouf", "pour", "pout", "pows", "pram", "prao",
> "prat", "prau", "pray", "pree", "prep", "prex", "prey", "prez", "prig", "prim",
> "proa", "prod", "prof", "prog", "prom", "prop", "pros", "prow", "psis", "psst",
> "pubs", "puce", "puck", "puds", "puff", "pugh", "pugs", "puja", "puke", "pula",
> "pule", "puli", "pull", "pulp", "puls", "puma", "pump", "puna", "pung", "punk",
> "puns", "punt", "puny", "pupa", "pups", "pure", "puri", "purl", "purr", "purs",
> "push", "puss", "puts", "putt", "putz", "pyas", "pyes", "pyic", "pyin", "pyre",
> "qaid", "qats", "qoph", "quad", "quag", "quai", "quay", "quey", "quid", "quin",
> "quip", "quit", "quiz", "quod", "race", "rack", "racy", "rads", "raff", "raft",
> "raga", "rage", "ragi", "rags", "raia", "raid", "rail", "rain", "raja", "rake",
> "raki", "rale", "rami", "ramp", "rams", "rand", "rang", "rani", "rank", "rant",
> "rape", "raps", "rapt", "rare", "rase", "rash", "rasp", "rate", "rath", "rato",
> "rats", "rave", "raws", "raya", "rays", "raze", "razz", "read", "real", "ream",
> "reap", "rear", "rebs", "reck", "recs", "redd", "rede", "redo", "reds", "reed",
> "reef", "reek", "reel", "rees", "refs", "reft", "regs", "reif", "rein", "reis",
> "rely", "rems", "rend", "rent", "repo", "repp", "reps", "resh", "rest", "rete",
> "rets", "revs", "rhea", "rhos", "rhus", "rial", "rias", "ribs", "rice", "rich",
> "rick", "ride", "rids", "riel", "rife", "riff", "rifs", "rift", "rigs", "rile",
> "rill", "rime", "rims", "rimy", "rind", "ring", "rink", "rins", "riot", "ripe",
> "rips", "rise", "risk", "rite", "ritz", "rive", "road", "roam", "roan", "roar",
> "robe", "robs", "rock", "rocs", "rode", "rods", "roes", "roil", "role", "rolf",
> "roll", "romp", "roms", "rood", "roof", "rook", "room", "root", "rope", "ropy",
> "rose", "rosy", "rota", "rote", "roti", "rotl", "roto", "rots", "roue", "roup",
> "rout", "roux", "rove", "rows", "rube", "rubs", "ruby", "ruck", "rudd", "rude",
> "rued", "ruer", "rues", "ruff", "ruga", "rugs", "ruin", "rule", "ruly", "rump",
> "rums", "rune", "rung", "runs", "runt", "ruse", "rush", "rusk", "rust", "ruth",
> "ruts", "ryas", "ryes", "ryke", "rynd", "ryot", "sabe", "sabs", "sack", "sacs",
> "sade", "sadi", "safe", "saga", "sage", "sago", "sags", "sagy", "said", "sail",
> "sain", "sake", "saki", "sale", "sall", "salp", "sals", "salt", "same", "samp",
> "sand", "sane", "sang", "sank", "sans", "saps", "sard", "sari", "sark", "sash",
> "sass", "sate", "sati", "saul", "save", "sawn", "saws", "says", "scab", "scad",
> "scag", "scam", "scan", "scar", "scat", "scop", "scot", "scow", "scry", "scud",
> "scum", "scup", "scut", "seal", "seam", "sear", "seas", "seat", "secs", "sect",
> "seed", "seek", "seel", "seem", "seen", "seep", "seer", "sees", "sego", "segs",
> "seif", "seis", "self", "sell", "sels", "seme", "semi", "send", "sene", "sent",
> "sept", "sera", "sere", "serf", "sers", "seta", "sets", "sett", "sewn", "sews",
> "sext", "sexy", "shad", "shag", "shah", "sham", "shat", "shaw", "shay", "shea",
> "shed", "shes", "shew", "shim", "shin", "ship", "shit", "shiv", "shmo", "shod",
> "shoe", "shog", "shoo", "shop", "shot", "show", "shri", "shul", "shun", "shut",
> "sial", "sibb", "sibs", "sice", "sick", "sics", "side", "sift", "sigh", "sign",
> "sike", "sild", "silk", "sill", "silo", "silt", "sima", "simp", "sims", "sine",
> "sing", "sinh", "sink", "sins", "sipe", "sips", "sire", "sirs", "site", "sith",
> "sits", "size", "sizy", "skag", "skas", "skat", "skee", "skeg", "skep", "skew",
> "skid", "skim", "skin", "skip", "skis", "skit", "slab", "slag", "slam", "slap",
> "slat", "slaw", "slay", "sled", "slew", "slid", "slim", "slip", "slit", "slob",
> "sloe", "slog", "slop", "slot", "slow", "slub", "slue", "slug", "slum", "slur",
> "slut", "smew", "smit", "smog", "smug", "smut", "snag", "snap", "snaw", "sned",
> "snib", "snip", "snit", "snob", "snog", "snot", "snow", "snub", "snug", "soak",
> "soap", "soar", "sobs", "sock", "soda", "sods", "sofa", "soft", "soil", "soja",
> "soke", "sola", "sold", "sole", "soli", "solo", "sols", "soma", "some", "sone",
> "song", "sons", "sook", "soon", "soot", "soph", "sops", "sora", "sorb", "sord",
> "sore", "sori", "sorn", "sort", "soth", "sots", "souk", "soul", "soup", "sour",
> "sous", "sown", "sows", "soya", "soys", "spae", "span", "spar", "spas", "spat",
> "spay", "spaz", "spec", "sped", "spew", "spic", "spik", "spin", "spit", "spiv",
> "spot", "spry", "spud", "spue", "spun", "spur", "sris", "stab", "stag", "star",
> "stat", "staw", "stay", "stem", "step", "stet", "stew", "stey", "stir", "stoa",
> "stob", "stop", "stow", "stub", "stud", "stum", "stun", "suba", "subs", "such",
> "suck", "sudd", "suds", "sued", "suer", "sues", "suet", "sugh", "suit", "sulk",
> "sulu", "sumo", "sump", "sums", "sung", "sunk", "sunn", "suns", "supe", "sups",
> "suqs", "sura", "surd", "sure", "surf", "suss", "swab", "swag", "swam", "swan",
> "swap", "swat", "sway", "swig", "swim", "swob", "swop", "swot", "swum", "syce",
> "syke", "syli", "sync", "syne", "syph", "tabs", "tabu", "tace", "tach", "tack",
> "taco", "tact", "tads", "tael", "tags", "tail", "tain", "taka", "take", "tala",
> "talc", "tale", "tali", "talk", "tall", "tame", "tamp", "tams", "tang", "tank",
> "tans", "taos", "tapa", "tape", "taps", "tare", "tarn", "taro", "tarp", "tars",
> "tart", "task", "tass", "tate", "tats", "taus", "taut", "tavs", "taws", "taxa",
> "taxi", "teak", "teal", "team", "tear", "teas", "teat", "teds", "teed", "teel",
> "teem", "teen", "tees", "teff", "tegs", "tela", "tele", "tell", "tels", "temp",
> "tend", "tens", "tent", "tepa", "term", "tern", "test", "teth", "tets", "tews",
> "text", "thae", "than", "that", "thaw", "thee", "them", "then", "thew", "they",
> "thin", "thio", "thir", "this", "thou", "thro", "thru", "thud", "thug", "thus",
> "tick", "tics", "tide", "tidy", "tied", "tier", "ties", "tiff", "tike", "tiki",
> "tile", "till", "tils", "tilt", "time", "tine", "ting", "tins", "tint", "tiny",
> "tipi", "tips", "tire", "tirl", "tiro", "titi", "tits", "tivy", "toad", "toby",
> "tods", "tody", "toea", "toed", "toes", "toff", "toft", "tofu", "toga", "togs",
> "toil", "toit", "toke", "tola", "told", "tole", "toll", "tolu", "tomb", "tome",
> "toms", "tone", "tong", "tons", "tony", "took", "tool", "toom", "toon", "toot",
> "tope", "toph", "topi", "tops", "tora", "torc", "tore", "tori", "torn", "toro",
> "torr", "tors", "tort", "tory", "tosh", "toss", "tost", "tote", "tots", "tour",
> "tout", "town", "tows", "towy", "toyo", "toys", "trad", "tram", "trap", "tray",
> "tree", "tref", "trek", "tret", "trey", "trig", "trim", "trio", "trip", "trod",
> "trop", "trot", "trow", "troy", "true", "trug", "tsar", "tsks", "tuba", "tube",
> "tubs", "tuck", "tufa", "tuff", "tuft", "tugs", "tuis", "tule", "tump", "tuna",
> "tune", "tung", "tuns", "tups", "turd", "turf", "turk", "turn", "tush", "tusk",
> "tuts", "tutu", "twae", "twas", "twat", "twee", "twig", "twin", "twit", "twos",
> "tyee", "tyer", "tyes", "tyke", "tyne", "type", "typo", "typp", "typy", "tyre",
> "tyro", "tzar", "udos", "ugly", "ukes", "ulan", "ulus", "umps", "unai", "unau",
> "unbe", "unci", "unco", "unde", "undo", "undy", "unit", "unto", "upas", "updo",
> "urbs", "urds", "urea", "urns", "ursa", "urus", "used", "user", "uses", "utas",
> "uvea", "vacs", "vagi", "vail", "vain", "vair", "vale", "vamp", "vane", "vang",
> "vans", "vara", "vars", "vary", "vasa", "vase", "vast", "vats", "vatu", "vaus",
> "vavs", "vaws", "veal", "veep", "veer", "vees", "veil", "vein", "vela", "veld",
> "vena", "vend", "vent", "vera", "verb", "vert", "very", "vest", "veto", "vets",
> "vext", "vial", "vibe", "vice", "vide", "vied", "vier", "vies", "view", "viga",
> "vigs", "vile", "vill", "vims", "vina", "vine", "vino", "viny", "viol", "virl",
> "visa", "vise", "vita", "viva", "vive", "voes", "vole", "volt", "vote", "vows",
> "vrow", "vugg", "vugh", "vugs", "wabs", "wack", "wade", "wadi", "wads", "wady",
> "waes", "waff", "waft", "wage", "wags", "waif", "wail", "wain", "wair", "wait",
> "wake", "wale", "walk", "wall", "waly", "wame", "wand", "wane", "wans", "want",
> "wany", "waps", "ward", "ware", "wark", "warm", "warn", "warp", "wars", "wart",
> "wary", "wash", "wasp", "wast", "wats", "watt", "wauk", "waul", "waur", "wave",
> "wavy", "wawl", "waws", "waxy", "ways", "weak", "weal", "wean", "wear", "webs",
> "weds", "weed", "week", "weel", "ween", "weep", "weer", "wees", "weet", "weft",
> "weir", "weld", "well", "welt", "wend", "wens", "went", "wept", "were", "wert",
> "west", "wets", "wham", "whap", "what", "whee", "when", "whet", "whew", "whey",
> "whid", "whig", "whim", "whin", "whip", "whir", "whit", "whiz", "whoa", "whom",
> "whop", "whys", "wich", "wick", "wide", "wife", "wigs", "wild", "wile", "will",
> "wilt", "wily", "wimp", "wind", "wine", "wing", "wink", "wino", "wins", "winy",
> "wipe", "wire", "wiry", "wise", "wish", "wisp", "wiss", "wist", "wite", "with",
> "wits", "wive", "woad", "woes", "wogs", "woke", "woks", "wold", "wolf", "womb",
> "wonk", "wons", "wont", "wood", "woof", "wool", "woos", "wops", "word", "wore",
> "work", "worm", "worn", "wort", "wost", "wots", "wove", "wows", "wrap", "wren",
> "writ", "wuss", "wych", "wyes", "wyle", "wynd", "wynn", "wyns", "wyte", "xyst",
> "yack", "yaff", "yagi", "yaks", "yald", "yams", "yang", "yank", "yaps", "yard",
> "yare", "yarn", "yaud", "yaup", "yawl", "yawn", "yawp", "yaws", "yays", "yeah",
> "yean", "year", "yeas", "yech", "yeld", "yelk", "yell", "yelp", "yens", "yerk",
> "yeti", "yett", "yeuk", "yews", "yids", "yill", "yins", "yipe", "yips", "yird",
> "yirr", "yobs", "yock", "yodh", "yods", "yoga", "yogh", "yogi", "yoke", "yoks",
> "yolk", "yond", "yoni", "yore", "your", "yowe", "yowl", "yows", "yuan", "yuca",
> "yuch", "yuck", "yuga", "yuks", "yule", "yups", "yurt", "ywis", "zags", "zany",
> "zaps", "zarf", "zeal", "zeds", "zees", "zein", "zeks", "zerk", "zero", "zest",
> "zeta", "zigs", "zill", "zinc", "zing", "zins", "zips", "ziti", "zits", "zoea",
> "zone", "zonk", "zoom", "zoon", "zoos", "zori", "zyme" ]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment