Skip to content

Instantly share code, notes, and snippets.

@pragdave
Last active December 13, 2019 18:03
Show Gist options
  • Save pragdave/68f56f8d9e36605ce44a7b0e1cb22203 to your computer and use it in GitHub Desktop.
Save pragdave/68f56f8d9e36605ce44a7b0e1cb22203 to your computer and use it in GitHub Desktop.
/// <summary>
/// Builds a map where the keys are word signatures and
/// each value is the list of words that share that signature.
/// The signature of a word is simply a string containing
/// the word's letters, sorted. Thus "dog" and "god" will
/// both have the signature "dgo", and the entry in the map
/// with that key will be those two words.
///
/// This let's us quickly find anagrams
/// </summary>
module AnagramMap =
type T = Map<string, string list>
let empty : T = Map.empty
let signatureOf (word:string) =
word.ToLower()
|> Seq.sort
|> System.String.Concat
let addOrUpdate (anagrams:T) word : T =
let signature = signatureOf word
let wordsWithSignature =
match anagrams.TryFind(signature) with
| Some words -> word :: words
| None -> [ word ]
in
Map.add signature wordsWithSignature anagrams
let buildDictionary wordList =
Seq.fold addOrUpdate empty wordList
let anagramsOf word (anagrams:T) =
Map.tryFind (signatureOf word) anagrams
let otherAnagramsOf word =
Map.tryFind (signatureOf word)
@swlaschin
Copy link

swlaschin commented Dec 12, 2019

Overall, I wouldn't worry about all the different possible implementations that you could do. It's easy to get caught up in over refinement and being too clever. :)

Your original version is fine -- it's clear and understandable and that's the most important thing.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment