Find-A-Word: Memorial

This tool is no longer maintained
Created: 2008-09-21 and last updated 2018-06-22
Tagged: tools memorial

I’m no longer maintaining this tool. Check out wordfind.com for the same functionality.

Dreams that never quite materialized

I had big plans to update this tool. For example, I wanted to experiment with storing the word list in various data structures to make it faster to locate matches.

I also wanted to display live matches as you entered the letters.

Even the insanely innefficient brute force method you see below was still very fast, but I wasn’t quite comfortable with having it run every time you pressed a key…​

Anyway, I always have more plans than time, so this one is getting shut down for now to make way for bigger priorities.

The Ancient Source

It’s unfortunate when folks take things offline without a trace. So rather than be part of the problem, I’m going to dump the entire source of the old PHP application here.

It’s not interesting from a computer science standpoint other than to demonstrate how powerful computers are - they can load a 550Kb text file full of words and run loops nested three deep to sort the list and return the results in a split second!

$minimum = 3;
$letters = '';
$lensort = false;

if(Darts::isWebData('letters')){
  $have_searched = true;
  $letters = Darts::webData('letters');
  $lensort = Darts::isWebData('sort-by-length') ? true : false;
  $letters = strtolower($letters);
  $minimum = intval(Darts::webData('minimum'));
  $letter_array = str_split(preg_replace('/\s+/', '', $letters));
  sort($letter_array);
  $letterlist = implode('', $letter_array);
  $len = strlen($letterlist);
  $uniqueletter_array = implode('', array_unique($letter_array));

  $all_letter_words = array();
  $some_letter_words = array();
  $at_least_one_match = false;

  // read dictionary file
  $handle = @fopen('include/dictionary.txt', "r");
  if ($handle){
    while(($word = fgets($handle)) !== false){
      $word = trim($word);
      $wlen = strlen($word);
      if($wlen<$minimum){
        continue; // word is too short for our minimum!
      }
      $l = $letterlist; // make a copy of the letter list
      for($i=0; $i<$wlen; $i++){
        for($j=0; $j<$len; $j++){
          if($word[$i]==$l[$j]){
            $l[$j] = '#';
            continue 2;  // go to next letter in $word
          }
        }
        continue 2; // go to next word entirely
      }

      $at_least_one_match = true;

      // it's all #s, so all of the letters have been used up!
      if(preg_match('/#{'.$len.'}/', $l)){
        array_push($all_letter_words, $word);
      }
      else{
        array_push($some_letter_words, $word);
      }


      if($lensort){
        usort($all_letter_words,'lensort');
        usort($some_letter_words,'lensort');
      }

    }
    if (!feof($handle)) {
      echo "Darn it, ran into an error while reading the dictionary file!  Sorry.";
    }
    fclose($handle);
  }
}


// via http://stackoverflow.com/questions/838227/php-sort-an-array-by-the-length-of-its-values
function lensort($a,$b){
    return strlen($b)-strlen($a);
}



?>

[include 'head.php']

<div id="content">

<h1>[title]</h1>
<h2>Find a word which contains all of your provided letters</h2>

<form action="[selfnameonly]#scroll-to-results" method="post">
  <ol>
  <li>
    <label for="letters">Letters (spaces will be ignored)</label>
    <input type="text" [formtext letters] id="letters">
  </li>
  <li>
    <label for="minimum">Minimum length of matched words ('1' will return all results)</label>
    <input type="text" id="minimum" [formtext minimum] size="3">
  </li>
  <li>
    <input type="checkbox" name="sort-by-length" [iftrue lensort]checked="checked"[end]>
    <label for="sort-by-length">Sort results by length (will otherwise be sorted alphabetically)</label>
  </li>
  <li>
    <input type="submit" value="Find!">
  </li>
  </ol>
</form>

<p>Provide a list of letters (or a word) and get back any words which use some or all
of the letters.  To find the word "cattle", you would have to provide two letter t's
in your list of letters.  You can also limit the results to words of a minimum length
 so that short words like "a" and "an" can be eliminated.</p>

<p>These results are particularly suitable
for creating acronyms and transforming words.   It does not find "anagrams", as those
can be multiple words.
Note: this also works particularly
well for getting unstuck while finding the longest word(s) in the free
<a href="http://www.amazon.com/Every-Word/dp/B003P37FW0">Every Word</a> game on the Amazon
Kindle, as well as other word games.  Enjoy!</p>

<p><em>May 16, 2013:</em> I've finally replaced the old dictionary with a vastly better one.  Specifically the '2of4brif.txt' dictionary from the <a href="http://wordlist.sourceforge.net/">12Dicts package</a> by Kevin Atkinson. We are all in Kevin's debt for this excellent word list. Thanks Kevin!</p>

<p><em>Feb 2, 2011:</em> I've added a new feature! You can now click on a word to see
its definition on Merriam-Webster's website.</p>


[ifset have_searched]
  <a name="scroll-to-results"></a>
  [iftrue at_least_one_match]

    [iftrue all_letter_words]
      <h2>Words using the all of the letters [letterlist]:</h2>
      <ul style="font-family: monospace">
        [loop all_letter_words as w]
        <li><a href="http://www.m-w.com/dictionary/[w]">[w]</a></li>
        [end]
      </ul>
    [end]

    [iftrue some_letter_words]
      <h2>Words using some of the letters [letterlist]:</h2>
      <ul style="font-family: monospace">
        [loop some_letter_words as w]
        <li><a href="http://www.m-w.com/dictionary/[w]">[w]</a></li>
        [end]
      </ul>
    [end]

  [else]
    <h2>No words found using '[letterlist]'</h2>
    <p>Sorry, no English words found which matched all of your letters.</p>
  [end]
[end]


</div>

[include 'foot.php']