Skip to content

Instantly share code, notes, and snippets.

@sgoguen
Created February 13, 2019 04:04
Show Gist options
  • Save sgoguen/9c2386328b410435f2977947e5fe369c to your computer and use it in GitHub Desktop.
Save sgoguen/9c2386328b410435f2977947e5fe369c to your computer and use it in GitHub Desktop.
Wheel of Fortune Solver
// First, clone the word list project here: https://github.com/dwyl/english-words.git
// Then save this file in the same folder and run!
open System.IO
// Ok... Here's how it works...
// First, we load all the words from the Moby text fil
let allTheWords = File.ReadAllLines("words.txt")
// Next, we need a function that extracts a char *set* from
// a word.
let wordToSet(word:string) =
// Let's remove the _ chars and pipe the char array to Set.ofArray
word.Replace("_", "").ToCharArray() |> Set.ofArray
// Here we turn a list of words into a char set
let getAllUsedLetters words =
words
|> Array.map wordToSet
// We use the fold operator to turn the set list
// into a single set. Set.union merges two sets
// We need to seed our fold with Set.empty
|> Array.fold Set.union Set.empty
// We need to know all the letters available
let allLetters = "qwertyuiopasdfghjklzxcvbnm" |> wordToSet
// Now the magic. Given any word, and a set of unused letters,
// we want to create a regex that lets us look for words
// that might match our word.
let partialWordToRegex (unusedLetters:Set<char>) (word:string) =
// Give me a list of letters
let letters = [ for l in Set.toSeq(unusedLetters) -> l ]
// Turn it into a regex fragment [abeksuf]
let emptyChar = "[" + System.String.Concat(letters) + "]"
// Replace every _ in the word with our regex pattern
System.Text.RegularExpressions.Regex("^" + word.Replace("_", emptyChar) + "$")
// Given a list of words, give us a list of regexes to find
// words in our dictionary.
let makeRegex (words:string[]) =
// Create a set of all the used letters so far
let usedLetters = getAllUsedLetters words
// Now, get us a set of unused letters using Set.difference
let unusedLetters = usedLetters |> Set.difference allLetters
// Then return our regex list
[| for word in words do
yield word |> partialWordToRegex unusedLetters |]
// Finally, we do a simple search.
let find (inWords:string) =
// Get our words
let inWords = inWords.ToLower().Split(' ')
for i in 0..inWords.Length - 1 do
let word = inWords.[i]
let r = (inWords |> makeRegex).[i]
// Find each word
let found = allTheWords
|> Array.filter (fun w -> r.IsMatch(w.ToLower()))
|> Array.sortDescending
// And print.
printfn "%i - %s (%i) %A" i word (found.Length) found
// Voila!!!
// I wrote up some F# functions to help my wife play
// Wheel of Fortune when she gets stuck, and she's stuck
// on this particular puzzle.
// I think I nearly have it. This program basically looks through
// the Moby word list and search for words that match these patterns.
// I'll show you how it works...
find "so_t_er_ fr_e_ fs_ar_ ca__ fo_ s_ea_ers wxgb"
// Southern Fried FSharp Call for Speakers!
/// I solved it!
///
/// Also, you have until Friday to submit your talk for
/// Southern Fried F# --- April 13 - Raleigh, NC
///
/// See you there!!!!
// The words below are the suggestions
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment