Code of larry
<html>
  <head>
    <title>PHP-Editors Contest B3 - Jumbled Words - June 2003</title>
  </head>

  <body>
<?php
  
/* | PHP-Editors Contest - June 2003
   * | Contest B3 (Jumbled Words)
   * +---------------------------------------------------------------------------+
   * | Title           : Contest B3 - Jumbled Words
   * | Filename        : contest_b3.php
   * | Author          : Larry J. Rutledge (larry@ixoyedesign.com)
   * | Created         : June 3, 2003
   * | Last Modified   : June 5, 2003
   * +---------------------------------------------------------------------------+
   * | Description     : Find supplied word(s) in a sentence. The word(s) you
   * |                 : find will be intact, but the sentences will be
   * |                 : muddled-up and may have many unused letters. There are
   * |                 : two blank letters available, per list, which can be used
   * |                 : to complete words. Blanks can be any letter, but they
   * |                 : cannot be the same, for example:
   * |                 : Blank 1 = g, Blank 2 = h (valid)
   * |                 : Blank 1 = f, Blank 2 = f (invalid)
   * |                 :
   * |                 : Input
   * |                 : 1. The input contains pairs of lists and sentences.
   * |                 : 2. The list gives the words to search for in the
   * |                 :    following sentence.
   * |                 : 3. Lists are terminated by a comma.
   * |                 : 4. All letters are in lower case.
   * |                 : 5. Words are at most 20 letters long and are separated
   * |                 :    by a single space.
   * |                 : 6. Each line is at most 80 characters long.
   * |                 : 7. Sentences may occupy more than one line, and are
   * |                 :    terminated by a full stop.
   * |                 : 8. The input will be given in a text file named
   * |                 :    "lists.txt" and will be stored in the same directory.
   * |                 :
   * |                 : Output
   * |                 : 1. For each pair of list and sentence, find the words
   * |                 :    from the list that appear in the sentence with the
   * |                 :    letters shuffled.
   * |                 : 2. Print these words in order of highest character
   * |                 :    count, separated by a single space.
   * |                 : 3. Highlight (in red) any letters used from your blanks,
   * |                 :    all other letters should be black.
   * |                 : 4. If no words from the list match the words in the
   * |                 :    sentence, just print a blank line.
   * |                 : 5. On the last line print the total number of letters
   * |                 :    found (including any blanks used).
   * |                 :
   * |                 : EACH LETTER CAN ONLY BE USED ONCE!!
   * |                 :
   * |                 : Sample Input
   * |                 :
   * |                 : string constant variable sausages,
   * |                 : tstnacon bleiangrav igtni ksiypappsle.
   * |                 : class function objects hypertext preprocessor,
   * |                 : sslas nyyoitcf teztxrpyhre krtbhwopqowo
   * |                 : jksksjajajahshshj.
   * |                 :
   * |                 : Sample Output
   * |                 :
   * |                 : constant variable string
   * |                 :                     -
   * |                 : hypertext objects class
   * |                 :              --
   * |                 : 43
   * |                 :
   * +---------------------------------------------------------------------------+
   * | Restrictions    : 1. Must run on Windows and Unix systems.
   * |                 : 2. Must run with PHP 4.2 (register_globals OFF)
   * |                 : 3. No third part PHP extensions (other than ones
   * |                 :    supplied with PHP 4.2 on PHP.NET)
   * |                 : 4. Maximum execution time - 60 seconds
   * +---------------------------------------------------------------------------+
   * | Instructions    : Put a "lists.txt" file in the same directory as this
   * |                 : script. The file should consist of pairs of lines. The
   * |                 : first line should be a list of words separated by spaces
   * |                 : and terminated by a comma (,). The second line should be
   * |                 : a list of letters terminated by a period (.).
   * +---------------------------------------------------------------------------+
   * | Important Note  : No notes for this project
   * |
   * | History         : Version  Date        Author   Description
   * |                   -------  ----------  ------   --------------------------
   * |                    1.0.0   07/03/2003   LJR     Initial Development
   * |                    1.0.1   07/05/2003   LJR     Added weighting to improve
   * |                                                 results.
   * |
   * +---------------------------------------------------------------------------+
   * | Proposed
   * | Revisions       : 1. No proposed revisions at this time.
   * +---------------------------------------------------------------------------+
   */

   // Constant Declarations
   // ---------------------

   // Names used for user-defined sorting routines
   
DEFINE("__USER_SORT_DIFFERENCE__",  "usort_diff");
   
DEFINE("__USER_SORT_WEIGHTS__",     "usort_weight");
   
DEFINE("__USER_SORT_REV_WEIGHTS__""usort_rev_weight");
   
DEFINE("__USER_SORT_REV_LENGTH__",  "usort_rev_len");

   
// Delimiter characters - used to separate out lines from source.
   
DEFINE("__WORD_DELIM__",   ',');
   
DEFINE("__LETTER_DELIM__"'.');

   
// Index Positions for Statistics array
   
DEFINE("__STATS_NEED__"0);
   
DEFINE("__STATS_HAVE__"1);
   
DEFINE("__STATS_DIFF__"2);

   
// Index Positions for Weight Array
   
DEFINE("__WEIGHT_COUNT__"0);
   
DEFINE("__WEIGHT_TOTAL__"1);
   
DEFINE("__WEIGHT_PCT__",   2);

   
// Index Positions identifying each "blank" in blank array
   
DEFINE("__BLANK__ONE__"0);
   
DEFINE("__BLANK__TWO__"1);

   
// Index Positions for sub-array in "blank" array
   
DEFINE("__BLANK_CHAR__"0);
   
DEFINE("__BLANK_WORD__"1);
   
DEFINE("__BLANK_POS__",  2);

   new 
Searcher;

   
/**   Function: usort_diff
    *    ----------------------------------------------------------------------
    *    Purpose     : This method sorts a "statistic" array based on the
    *                : difference between what is needed and what is
    *                : available - for example, if the word list needs five (5)
    *                : of the letter 'a', but the letter list only has two (2),
    *                : then the value to be sorted on would be (-3).
    *                :
    *    Arguments   : a - First of two values to be compared
    *                : b - Second of two values to be compared
    *                :
    *    Assignments : None
    *                :
    *    Returns     : Returns an integer less than, equal to, or greater then
    *                : zero if the first argument ($a) is considered to be
    *                : respectively less than, equal to, or greater than the
    *                : second ($b)
    *                :
    *    Assumptions : None
    *                :
    *    Constraints : None
    */
   
function usort_diff($a$b) {
     if (
$a[__STATS_DIFF__] == $b[__STATS_DIFF__]) return 0;
     return (
$a[__STATS_DIFF__] < $b[__STATS_DIFF__]) ? -1;
   }

   
/**   Function: usort_weight
    *    ----------------------------------------------------------------------
    *    Purpose     : This method sorts a "weight" array based on the
    *                : weighting applied to the words in the original word
    *                : list. This weight is a number identifying how many of
    *                : its characters are potentialy unavailable in the letter
    *                : list. If the weights are equal, the the percentage is
    *                : used, which is calculated by the ratio of the weight to
    *                : the total number of characters in the word.
    *                :
    *    Arguments   : a - First of two values to be compared
    *                : b - Second of two values to be compared
    *                :
    *    Assignments : None
    *                :
    *    Returns     : Returns an integer less than, equal to, or greater than
    *                : zero if the first argument ($a) is considered to be
    *                : respectively less than, equal to, or greater than the
    *                : second ($b)
    *                :
    *    Assumptions : None
    *                :
    *    Constraints : None
    */
   
function usort_weight($a$b) {
     if (
$a[__WEIGHT_COUNT__] == $b[__WEIGHT_COUNT__]) {
       if (
$a[__WEIGHT_PCT__] == $b[__WEIGHT_PCT__]) {
         if (
$a[__WEIGHT_TOTAL__] == $b[__WEIGHT_TOTAL__]) return 0;
         return (
$a[__WEIGHT_TOTAL__] < $b[__WEIGHT_TOTAL__]) ? -1;
       }
       return (
$a[__WEIGHT_PCT__] < $b[__WEIGHT_PCT__]) ? -1;
     }
     return (
$a[__WEIGHT_COUNT__] < $b[__WEIGHT_COUNT__]) ? -1;
   }

   
/**   Function: usort_rev_weight
    *    ----------------------------------------------------------------------
    *    Purpose     : This method is the same as "usort_weight", except it
    *                : reverses the sort order.
    *                :
    *    Arguments   : a - First of two values to be compared
    *                  b - Second of two values to be compared
    *                :
    *    Assignments : None
    *                :
    *    Returns     : Returns an integer greater than, equal to, or less than
    *                  zero if the first argument ($a) is considered to be
    *                  respectively less than, equal to, or greater than the
    *                  second ($b)
    *                :
    *    Assumptions : None
    *                :
    *    Constraints : None
    */
   
function usort_rev_weight($a$b) {
     if (
$a[__WEIGHT_COUNT__] == $b[__WEIGHT_COUNT__0]) {
       if (
$a[__WEIGHT_PCT__] == $b[__WEIGHT_PCT__]) {
         if (
$a[__WEIGHT_TOTAL__] == $b[__WEIGHT_TOTAL__]) return 0;
         return (
$a[__WEIGHT_TOTAL__] < $b[__WEIGHT_TOTAL__]) ? : -1;
       }
       return (
$a[__WEIGHT_PCT__] < $b[__WEIGHT_PCT__]) ? : -1;
     }
     return (
$a[__WEIGHT_COUNT__] < $b[__WEIGHT_COUNT__]) ? : -1;
   }

   
/**   Function: usort_rev_len
    *    ----------------------------------------------------------------------
    *    Purpose     : This method sorts an array of strings from longest to
    *                  shortest. This is included to satisfy the requirement
    *                  that the final word list appear in this order.
    *                :
    *    Arguments   : a - First of two values to be compared
    *                  b - Second of two values to be compared
    *                :
    *    Assignments : None
    *                :
    *    Returns     : Returns an integer greater than, equal to, or less than
    *                  zero if the first argument ($a) is considered to be
    *                  respectively less than, equal to, or greater than the
    *                  second ($b)
    *                :
    *    Assumptions : None
    *                :
    *    Constraints : None
    */
   
function usort_rev_len($a$b) {
     if (
strlen($a) == strlen($b)) {
       if (
$a == $b) return 0;
       return (
$a $b) ? : -1;
     }
     return (
strlen($a) < strlen($b)) ? : -1;
   }

   
/**   Class: Searcher
    *    ----------------------------------------------------------------------
    *    Purpose     : This class is the main class for the word search script.
    *                : The constructor triggers the process and the conclusion
    *                : of the constructor code is also the conclusion of the
    *                : script.
    *                :
    *    Assumptions : None
    *                :
    *    Constraints : None
    */
   
class Searcher {
     
// Private Members - (should only be directly access by the class)

     // Name of file to be processed
     
var $_filename    "lists.txt";


     
// Arrays used by the script
     
var $_words       = array(); // Contains the list of words from the file
     
var $_letters     = array(); // Contains the list of letters from the file
     
var $_stats       = array(); // Contains statistics calculated during the
                                  // script processing
     
var $_weights     = array(); // Contains weightings for words, calculated
                                  // during the script processing

     
var $_foundWords  = array(); // Contains the words found that satisfy the
                                  // word search criteria

     
var $_blanks      = array(); // Contains information about the "blanks"
                                  // used during processing of a word list.
                                  // Identifies the blank used, the letter it
                                  // was used in, and the position in the word.

     
var $_currPos     0;       // Indicates the position in the file (used
                                  // cases where the file contains more than
                                  // one set of lines.

     
var $_letterCount 0;       // Maintains the count of letters added to
                                  // "$_foundWords" array. Used for reporting.

     /**   Accessor: getFilename
      *    ----------------------------------------------------------------------
      *    Purpose     : Used to treat the "private" member as a property
      *                :
      *    Arguments   : None
      *                :
      *    Assignments : None
      *                :
      *    Returns     : Contents of private member "_filename"
      *                :
      *    Assumptions : None
      *                :
      *    Constraints : None
      */
     
function getFilename() {
       return 
$this->_filename;
     }

     
/**   Mutator: setFilename
      *    ----------------------------------------------------------------------
      *    Purpose     : Used to treat the "private" member as a property
      *                :
      *    Arguments   : _value - contains value to assign to property.
      *                :
      *    Assignments : Sets contents of private member "_filename"
      *                :
      *    Returns     : None
      *                :
      *    Assumptions : None
      *                :
      *    Constraints : None
      */
     
function setFilename($_value) {
       if (
$this->_filename != $_value) {
         
$this->_filename $_value;
       }
     }

     
/**   Function: _countLetters
      *    ----------------------------------------------------------------------
      *    Purpose     : Counts the number of lowercase characters in a string.
      *                : Only counts the letters 'a' through 'z', no symbols,
      *                : numbers, or spaces.
      *                :
      *    Arguments   : _value - The string to be counted
      *                :
      *    Assignments : None
      *                :
      *    Returns     : Returns an integer value indicating the number of
      *                : characters contained in "_value"
      *                :
      *    Assumptions : None
      *                :
      *    Constraints : None
      */
     
function _countLetters($_value) {
       
$_count 0;
       for (
$iCount=0;$iCount<strlen($_value);$iCount++) {
         
$_char substr($_value,$iCount,1);
         if (
preg_match("/[a-z]/",$_char)) $_count++;
       }

       return 
$_count;
     }

     
/**   Function: _readLine
      *    ----------------------------------------------------------------------
      *    Purpose     : Returns a single line from a file, where a "line" is
      *                : defined by a sequence of characters followed by a
      *                : specific delimiter, ignoring carriage return and line
      *                : feed characters. The result is returned as a single
      *                : string with all characters as they were in the file,
      *                : except the carriage returns and line feeds are removed.
      *                : Also, the delimiter is removed from the source data.
      *                :
      *    Arguments   : _fp   - File Pointer obtained when the source file was
      *                :          opened.
      *                : delim - The delimiter character used to identify the
      *                :          end of a logical line.
      *                :
      *    Assignments : None
      *                :
      *    Returns     : A string containing the contents of a "line" from the
      *                : source file.
      *                :
      *    Assumptions : Delimiter must always appear physically as the last
      *                : character on a line, even if the logical line extends
      *                : over multiple lines.
      *                :
      *    Constraints : None
      */
     
function _readLine($_fp$delim) {
       
$_line "";
       
$line  "";

       
// As long as we don't reach the end of the file and we don't have the
       // delimiter, keep reading lines from the file and appending them
       // together.
       
while ((!feof($_fp)) && (substr($_line,-1,1)!=$delim)) {
         
$_line rtrim(fgets($_fp,1024));  // rtrim removes carriage returns
                                            // and line feeds
         
$line .= $_line;
       }

       if (
strlen($line)>0) {
         return 
substr($line,0,-1);  // Remove delimiter character
       
}
       else {
         return 
null;
       }
     }

     
/**   Function: read
      *    ----------------------------------------------------------------------
      *    Purpose     : Open the file for reading and call "_readLine()" to
      *                : obtain the word lists and letter lists.
      *                :
      *    Arguments   : None
      *                :
      *    Assignments : Adds word lists to the "_words" array.
      *                : Adds letter lists to the "_letters" array.
      *                :
      *    Returns     : None
      *                :
      *    Assumptions : None
      *                :
      *    Constraints : None
      */
     
function read() {
       if (
file_exists($this->getFilename()) &&
           
is_readable($this->getFilename())) {
         
$fp fopen($this->getFilename(), "r")
               or die(
"An error occurred while attempting to open ".
                      
$this->getFilename());

         while (!
feof($fp)) {
           
$temp $this->_readLine($fp__WORD_DELIM__);
           if (!
is_null($temp)) {
             
array_push($this->_words$temp);
           }

           
$temp $this->_readLine($fp__LETTER_DELIM__);
           if (!
is_null($temp)) {
             
array_push($this->_letters$temp);
           }
         }
       }
       else {
         die (
$this->getFilename()." doesn't exist or is not readable.");
       }
     }

     
/**   Function: _checkBlank
      *    ----------------------------------------------------------------------
      *    Purpose     : If either of the "blanks" have been used, check to see
      *                : if they appear in the provided word. If they do appear
      *                : in the word, there is no need to process the word
      *                : because this means that one of the letters it needs is
      *                : no longer available and the word cannot be completed.
      *                :
      *    Arguments   : _word - The word to be checked
      *                :
      *    Assignments : None
      *                :
      *    Returns     : True  - if "_word" contains at least one of the "blanks"
      *                : False - if "_word" does not contain either of the
      *                :         "blanks"
      *                :
      *    Assumptions : None
      *                :
      *    Constraints : None
      */
     
function _checkBlank($_word) {
       
$_found false;
       for (
$iCount=0;$iCount<strlen($_word);$iCount++) {
         
$_char substr($_word,$iCount,1);
         if ((
$_char == $this->_blanks[__BLANK__ONE__][__BLANK_CHAR__]) ||
             (
$_char == $this->_blanks[__BLANK__TWO__][__BLANK_CHAR__])) {
           
$_found true;
         }
       }

       return 
$_found;
     }

     
/**   Function: _setBlank
      *    ----------------------------------------------------------------------
      *    Purpose     : Attempts to assign a "blank". If either "blank" is open
      *                : the character isn't already stored in one of the
      *                : "blanks", then the character is assigned to the first
      *                : available blank. Also the word that used the blank and
      *                : the character position in the word where the blank
      *                : appears.
      *                :
      *    Arguments   : _char - The character to be used as a "blank"
      *                : _word - The word that needs to use the "blank"
      *                : _pos  - The position in the word where the character
      *                :          appears.
      *                :
      *    Assignments : none
      *                :
      *    Returns     : True  - If "_char" is successfully added as a blank.
      *                : False - If "_char" is not successfully added as a blank
      *                :
      *    Assumptions : None
      *                :
      *    Constraints : None
      */
     
function _setBlank($_char$_word$_pos) {
       
$_created false;

       if ((
$this->_blanks[__BLANK__ONE__][__BLANK_CHAR__]!=$_char) &&
           (
$this->_blanks[__BLANK__TWO__][__BLANK_CHAR__]!=$_char)) {
         if (
$this->_blanks[__BLANK__ONE__][__BLANK_CHAR__] == '') {
           
$this->_blanks[__BLANK__ONE__] = array($_char$_word$_pos);
           
$_created true;
         }
         else if (
$this->_blanks[__BLANK__TWO__][__BLANK_CHAR__] == '') {
           
$this->_blanks[__BLANK__TWO__] = array($_char$_word$_pos);
           
$_created true;
         }
       }

       return 
$_created;
     }

     
/**   Function: _resetBlank
      *    ----------------------------------------------------------------------
      *    Purpose     : While processing a word, if a "blank" has been added and
      *                : then it is determined that the word is not useable, it
      *                : necessary to remove the added "blank(s)".
      *                :
      *    Arguments   : _word - The word that was being processed.
      *                :
      *    Assignments : If the word appears in one of the "blank" slots, then
      *                : that slot in "_blank" is reset to an empty value.
      *                :
      *    Returns     : None
      *                :
      *    Assumptions : None
      *                :
      *    Constraints : None
      */
     
function _resetBlank($_word) {
       if (
$this->_blanks[__BLANK__ONE__][__BLANK_WORD__] == $_word) {
         
$this->_blanks[__BLANK__ONE__] = array(''""0);
       }
       else if (
$this->_blanks[__BLANK__TWO__][__BLANK_WORD__] == $_word) {
         
$this->_blanks[__BLANK__TWO__] = array(''""0);
       }
     }

     
/**   Function: _highlightBlank
      *    ----------------------------------------------------------------------
      *    Purpose     : Used for reporting - colors the "blank" character red.
      *                : Used the information stored in the "_blanks" array to
      *                : determine if the supplied word should be highlighted and
      *                : the position of the character to highlight.
      *                :
      *    Arguments   : _word - The word to highlight.
      *                :
      *    Assignments : None
      *                :
      *    Returns     : The provided word is returned, if the word requires
      *                : highlighting it will be included in the returned value.
      *                :
      *    Assumptions : None
      *                :
      *    Constraints : None
      */
     
function _highlightBlank($_word) {
       
$word $_word;

       for (
$iCount=0;$iCount<2;$iCount++) {
         if (
$_word == $this->_blanks[$iCount][__BLANK_WORD__]) {
           
$_temp $this->_blanks[$iCount][__BLANK_WORD__];
           
$word substr($_temp,0,$this->_blanks[$iCount][__BLANK_POS__]);
           
$word.= "<font color=\"red\">";
           
$word.= $this->_blanks[$iCount][__BLANK_CHAR__];
           
$word.= "</font>";
           
$word.= substr($_temp,$this->_blanks[$iCount][__BLANK_POS__]+1,
                          
strlen($_word));
         }
       }

       return 
$word;
     }

     
/**   Function: calcPercent
      *    ----------------------------------------------------------------------
      *    Purpose     : Calculates an integer percentage (0% - 100%) with no
      *                : decimals.
      *                :
      *    Arguments   : value - The value to compute the percentage from
      *                : total - The total amount
      *                :
      *    Assignments : None
      *                :
      *    Returns     : Integer percentage value (0 - 100).
      *                :
      *    Assumptions : None
      *                :
      *    Constraints : None
      */
     
function calcPercent($value$total) {
       return 
round(($value/$total)*100);
     }

     
/**   Function: calcStatistics
      *    ----------------------------------------------------------------------
      *    Purpose     : Calculates statistics based on the provided word and
      *                : letter lists. The statistics collected are the number
      *                : of each letter required by all the words, the number of
      *                : each letter available in the letter list and the
      *                : difference between those two counts.
      *                :
      *    Arguments   : _wordList   - A string containing the words to locate
      *                : _letterList - A string containing the available letters
      *                :
      *    Assignments : None
      *                :
      *    Returns     : An equivalent of the statistics array - to be assigned,
      *                : by the calling routine, to the class' stats array.
      *                :
      *    Assumptions : None
      *                :
      *    Constraints : None
      */
     
function calcStatistics($_wordList$_letterList) {
       
// Cycle through the word list and populate the "Need" column of the "stats"
       // array with the count of each occurrence of each letter in the words
       // provided.
       
for ($iCount 0$iCount strlen($_wordList); $iCount++) {
         
$_char substr($_wordList$iCount1);
         if (
preg_match("/[a-z]/"$_char)) {
           if (!isset(
$stats[$_char])) {
             
$stats[$_char] = array(100);
           }
           else {
             
$stats[$_char][__STATS_NEED__]++;
             
$stats[$_char][__STATS_DIFF__] = $stats[$_char][__STATS_HAVE__] -
                                              
$stats[$_char][__STATS_NEED__];
           }
         }
       }

       
// Cycle throught the letter list and populate the "Have" and "Diff"
       // columns of the "state" array with the count of each occurrence of
       // each letter in the letters provided and the difference between
       // that count and the count of needed letters.
       
for ($iCount 0$iCount strlen($_letterList); $iCount++) {
         
$_char substr($_letterList$iCount1);
         if (
preg_match("/[a-z]/"$_char)) {
           if (!isset(
$stats[$_char])) {
             
$stats[$_char] = array(011);
           }
           else {
             
$stats[$_char][__STATS_HAVE__]++;
             
$stats[$_char][__STATS_DIFF__] = $stats[$_char][__STATS_HAVE__] -
                                              
$stats[$_char][__STATS_NEED__];
           }
         }
       }

       return 
$stats;
     }

     
/**   Function: calcWordWeights
      *    ----------------------------------------------------------------------
      *    Purpose     : Calculates a weight for each word in the provided word
      *                : list. This weight is a count of how many letters in the
      *                : word may be unavailable. This is determined by checking
      *                : the "stats" array for the character, if the difference
      *                : column is less than '0' then there is not enough of that
      *                : character for all the words.
      *                :
      *                : For example:
      *                :  word = "class"
      *                :  stats['c'][DIFF] = -1
      *                :  stats['s'][DIFF} = -4
      *                :
      *                :  weight = 3
      *                :
      *    Arguments   : _words - Array where each entry is a word from the word
      *                :          list.
      *                :
      *    Assignments : None
      *                :
      *    Returns     : An equivalent of the weight array - to be assigned, by
      *                : the calling routine, to the class' weight array
      *                :
      *    Assumptions : None
      *                :
      *    Constraints : None
      */
     
function calcWordWeights($_words) {
       
$wordList explode(" "$_words);

       foreach (
$wordList as $word) {
         for (
$iCount 0$iCount strlen($word); $iCount++) {
           
$_char substr($word$iCount1);
           if (
preg_match("/[a-z]/"$_char)) {
             if (
$this->_stats[$_char][__STATS_DIFF__] < 0) {
               if (!isset(
$words[$word])) {
                 
$words[$word] = array(1strlen($word), 0);
               }
               else {
                 
$words[$word][__WEIGHT_COUNT__]++;
               }
             }
             else {
               if (!isset(
$words[$word])) {
                 
$words[$word] = array(0strlen($word), 0);
               }
             }
           }
         }
       }

       foreach (
$words as $key=>$val) {
         
$words[$key][__WORDS_PCT__] = 100 -
                                       
$this->calcPercent($val[0], $val[1]);
       }

       return 
$words;
     }

     
/**   Function: processWordList
      *    ----------------------------------------------------------------------
      *    Purpose     : Cycles through the provided word list, in the currently
      *                : sorted order, one word at a time and tries to match it
      *                : based on available provided letters. As a word is
      *                : is located, the available letter counts are reduced by
      *                : the amount used by the word. Also, when necessary,
      *                : "blank" letters are filled in - up to two "blanks".
      *                :
      *                : When the process starts, the "letter" list is copied to
      *                : the "letter_bucket" array for processing. Before each
      *                : word in the list is processed, the "letter_bucket" is
      *                : copied to "trans_bucket". This allows for a database
      *                : style transaction by providing a snap-shot of the array
      *                : prior to processing the word, so that if the word can
      *                : not be located, the "letter_bucket" can rollback to the
      *                : the counts prior to processing the current word.
      *                :
      *    Arguments   : _words   - array containing individual elements for
      *                :            each word.
      *                : _letters - "stats" array, use "HAVE" column
      *                :
      *    Assignments : Located words are appended to the "foundWords" array
      *                :
      *    Returns     : A string containing each of the words sorted from
      *                : largest to smallest, with a space between each word
      *                : and any "blanks" highlighted red.
      *                :
      *    Assumptions : None
      *                :
      *    Constraints : None
      */
     
function processWordList($_words$_letters) {
       
// Initialize "blank" array for new word list
       
$this->_blanks = array(
         array(
''""0),
         array(
''""0)
       );

       
// Make a work copy of the _letters array.
       
$letter_bucket $_letters;
       
// Initialize the _foundWords array to an empty array
       
$this->_foundWords = array();

       foreach (
$_words as $word=>$val) {
         
// Copy the letter bucket to a transaction bucket
         
$trans_bucket $letter_bucket;

         
// If the word contains a used "blank", skip processing because
         // the word can not be completed.
         
if (!$this->_checkBlank($word)) {
           
$foundWord true;
           for (
$iCount=0$iCount<strlen($word);$iCount++) {
             
$_char substr($word$iCount1);
             if ((isset(
$letter_bucket[$_char])) &&
                 (
$letter_bucket[$_char][__STATS_HAVE__] > 0)) {
               
// If we have the letter we need, reduce it in the
               // letter bucket
               
$letter_bucket[$_char][__STATS_HAVE__]--;
             }
             else if (!
$this->_setBlank($_char$word$iCount)) {
               
// If we didn't have the letter we needed and
               // we couldn't create a "blank", stop processing
               // the word.
               
$foundWord false;
             }
           }

           
// If we couldn't find the word, copy the transaction
           // bucket back to the letter bucket in order to reset it to
           // the state it was in prior to processing this word. Also,
           // remove any "blanks" created for this word.
           
if (!$foundWord) {
             
$letter_bucket $trans_bucket// Rollback transaction
             
$this->_resetBlank($word);
           }
           else {
             
// Word was found - Add it to the "foundWords" array
             
array_push($this->_foundWords$word);
           }
         }
       }

       
// Sort found words in order from largest to smallest based on
       // character length
       
uasort($this->_foundWords__USER_SORT_REV_LENGTH__);

       
// Create string containing found words, with a space between
       // the words and any used "blanks" highlighted
       
$word="";
       foreach (
$this->_foundWords as $_word) {
         
$word .= $this->_highlightBlank($_word)." ";
       }

       return 
$word;
     }

     
/**   Constructor
      *    ----------------------------------------------------------------------
      *    Purpose     : Used to initialize the class when a new instance is
      *                : created. In the case of this script, creating an
      *                : instance of the class causes the whole script to run.
      *                :
      *    Assumptions : None
      *                :
      *    Constraints : None
      */
     
function Searcher() {
       
// Read word and letter lists from file - if there is not an equal number
       // of word and letter lists, then there was a problem and the script must
       // stop processing.
       
$this->read();
       if (
count($this->_words)!=count($this->_letters)) die("There is not an ".
         
"equal number of word and letter lists");

       
// Initialize letter counter for whole run
       
$this->_letterCount 0;
       for (
$currPos=0$currPos<count($this->_words); $currPos++) {
         
// Calculate statistics for current word and letter list
         
$this->_stats $this->calcStatistics($this->_words[$currPos],
                                               
$this->_letters[$currPos]);
         
uasort($this->_stats__USER_SORT_DIFFERENCE__);

         
// Calculate weights for current word list
         
$this->_weights $this->calcWordWeights($this->_words[$currPos]);
         
uasort($this->_weights__USER_SORT_WEIGHTS__);

         
$_result $this->processWordList($this->_weights$this->_stats);
         
$count1 $this->_countLetters(strip_tags($_result));

         
uasort($this->_weights__USER_SORT_REV_WEIGHTS__);

         
$_result $this->processWordList($this->_weights$this->_stats);
         
$count2 $this->_countLetters(strip_tags($_result));

         
// First, process words ordered by weight in ascending order (smallest
         // to largest weight), then process in descending order. Use the
         // result of whichever one produces a larger count.
         
if ($count1 <= $count2) {
           
$this->_letterCount += $count2;
           echo 
$_result."<br>\n";
         }
         else {
           
uasort($this->_weights__USER_SORT_WEIGHTS__);
           
$_result $this->processWordList($this->_weights$this->_stats);

           
$this->_letterCount += $this->_countLetters(strip_tags($_result));

           echo 
$_result."<br>\n";
         }
       }

       echo 
$this->_letterCount;
     }
     function 
__construct() {
       
$this->Searcher();
     }
   }
?>
  </body>
</html>


Back to results


© Copyright 2003-2023 www.php-editors.com. The ultimate PHP Editor and PHP IDE site.