1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <title>Challenge #125 (Easy) - Word Analytics</title>
  5. <style type="text/css">
  6. * {
  7.     margin: 0;
  8.     padding: 0;
  9. }
  10. body {
  11.         background: #142404;
  12. }
  13. #container {
  14.     position: relative;
  15.     max-width: 90%;
  16.    
  17.     margin: 30px auto 10px auto;
  18.     background: #ADBD8D;
  19. }
  20. h1 {
  21.     position: relative;
  22.     max-width: 95%;
  23.     margin: 10px auto;
  24.     text-decoration: underline;
  25. }
  26. #challengeSpecs {
  27.     display: inline-block;
  28.     width: 100%;
  29.     border-bottom: 2px solid black;
  30. }
  31. #challengeSpecs p {
  32.     margin: 10px;
  33.     padding: 5px;
  34. }
  35. #challengeSpecs ul {
  36.     position: relative;
  37.     width: 75%;
  38.     margin: 10px auto 0 auto;
  39.    
  40. }
  41. #challengeSpecs ul li {
  42.     padding-left: 10px;
  43. }
  44. #challengeIO {
  45.     position: relative;
  46.     width: 90%;
  47.     margin: 10px auto;
  48.     margin-top: 0;
  49.     border: 2px solid black;
  50.     border-top: 0;
  51.     padding: 5px;
  52.     padding-top: 0;
  53. }
  54. #challengeIO ul, #challengeIO ol {
  55.     position: relative;
  56.     margin-left: 50px;;
  57. }
  58. #inputFormContainer {
  59.     position: relative;
  60.     text-align: center;
  61.     width: 80%;
  62.     margin: 20px auto;
  63.     border: 1px solid black;
  64.     border-bottom: 0;
  65.     padding-bottom: 10px;
  66. }
  67. form {
  68.     position: relative;
  69.     margin: 10px auto;
  70. }
  71. table * {
  72.     text-align: center;
  73.     padding: 2px;
  74. }
  75. </style>
  76. </head>
  77. <body>
  78. <div id="container">
  79.     <h1>/r/DailyProgramming Challenge #125 (Easy) - Word Analytics</h1>
  80.     <div id="challengeSpecs">
  81.         <p>
  82.         You're a newly hired engineer for a brand-new company that's building a "killer Word-like application". You've been specifically assigned to implement a tool that gives the user some details on common word usage, letter usage, and some other analytics for a given document! More specifically, you must read a given text file (no special formatting, just a plain ASCII text file) and print off the following details:
  83.         </p>
  84.         <ul>
  85.         <li>Number of words</li>
  86.         <li>Number of letters</li>
  87.         <li>Number of symbols (any non-letter and non-digit character, excluding white spaces)</li>
  88.         <li>Top three most common words (you may count "small words", such as "it" or "the")</li>
  89.         <li>Top three most common letters</li>
  90.         <li>Most common first word of a paragraph (paragraph being defined as a block of text with an empty line above it) (Optional bonus)</li>
  91.         <li>Number of words only used once (Optional bonus)</li>
  92.         <li>All letters not used in the document (Optional bonus)</li>
  93.         </ul>
  94.  
  95.     <p>Please note that your tool does not have to be case sensitive, meaning the word "Hello" is the same as "hello" and "HELLO".</p>
  96.     </div>
  97.     <div id="challengeIO">
  98. <?php
  99.     //Get input from POST or ask for input
  100.     if( isset( $_POST['submit'] ) ) {
  101.         //Check input file for errors
  102.         if( $_FILES['inputFile']['error'] > 0 ) {
  103.             echo "Error: " . $_FILES['inputFile']['error'] . "<br/>";
  104.         } else {
  105.             //Get the filepath and open it
  106.             $fileLocation = $_FILES['inputFile']['tmp_name'];
  107.             //Open and convert to lowercase for case insensitivity
  108.            
  109.             $lines = file( $fileLocation );
  110.             //Handle empty input file
  111.             if ( count($lines) < 1) {
  112.                 echo "The text file supplied is empty. Please try again.<br/>";
  113.             } else {
  114.                 //File has been successfully opened and dumped into $lines, time to process
  115.                
  116.                 //Processing vars
  117.                 $alphabet = array(
  118.                     'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h',
  119.                     'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p',
  120.                     'q', 'r', 's', 't', 'u', 'v', 'w', 'x',
  121.                     'y', 'z', '0', '1', '2', '3', '4', '5',
  122.                     '6', '7', '8', '9' ); //Alphanumeric characters
  123.                 $letterUse = array(); //alphabet[i] is used letterUse[i] times
  124.                 for( $i = 0; $i < 36; $i++ ) {
  125.                     //Fill with 0s
  126.                     array_push( $letterUse, 0 );
  127.                 }
  128.                 $allWords = array();
  129.                 $wordUse = array(); //allWords[i] is used wordUse[i] times
  130.                 $paragraphStarters = array();
  131.                 $psFrequency = array();
  132.                 $wordCount = 0;
  133.                 $letterCount = 0;
  134.                 $symbolCount = 0;
  135.                
  136.                 //We'll show the user the text being processed as we process it
  137.                 echo "<div id=\"inputText\"><br/><h2>Text Being Analyzed:</h2><br/><br/>";
  138.                 //Beginning of file counds as beginning of paragraph
  139.                 $pb = true;
  140.                 //Iterate over each line in the file
  141.                 foreach( $lines as $L ) {
  142.                     //If the line only contians a space, expect a paragraph to start
  143.                     if( preg_match( '/^\\s\\n$/', $L ) ) {
  144.                         //Print empty line and set flag
  145.                         echo "<br/>";
  146.                         $pb = true;
  147.                     } else {
  148.                         //If there are words on the line, print them
  149.                         echo "<p>" . $L . "</p>";
  150.                         //Then split the line into words
  151.                         $wordsInLine = strtolower( strtok( $L, ' ' ) );
  152.                         //Handle beginning of paragraph
  153.                         if( $pb ) {
  154.                             if( !in_array( $wordsInLine, $paragraphStarters ) ) {
  155.                                 //New paragraph beginning, add it to tracking arrays
  156.                                 array_push( $paragraphStarters, $wordsInLine );
  157.                                 array_push( $psFrequency, 1 );
  158.                             } else {
  159.                                 //It's in the array already, so increment its frequency
  160.                                 $index = array_search( $wordsInLine[0], $paragraphStarters );
  161.                                 $psFrequency[$index] += 1;
  162.                             }
  163.                             //Reset flag
  164.                             $pb = false;
  165.                         }
  166.                         //Now iterate over each word in the line
  167.                         while( $wordsInLine != false ) {
  168.                             //Accumulate word
  169.                             $wordCount += 1;
  170.                            
  171.                             //Iterate over letters and strip symbols
  172.                             $chars = str_split($wordsInLine);
  173.                             $word = "";
  174.                             foreach( $chars as $char ) {
  175.                                 if( ctype_alnum( $char ) ) {
  176.                                     $index = array_search( $char, $alphabet );
  177.                                     $letterUse[$index] += 1;
  178.                                     $letterCount += 1;
  179.                                     $word .= $char;
  180.                                 } else {
  181.                                     $symbolCount += 1;
  182.                                 }
  183.                             }
  184.                             //See if it's been used before
  185.                             if( !in_array( $word, $allWords ) ) {
  186.                                 array_push( $allWords, $word );
  187.                                 array_push( $wordUse, 1 );
  188.                             } else {
  189.                                 $index = array_search( $word, $allWords );
  190.                                 $wordUse[$index] += 1;
  191.                             }
  192.                            
  193.                         $wordsInLine = strtolower( strtok( ' ' ) );
  194.                         }
  195.                     }
  196.                 }
  197.                 echo "</div><hr/>";
  198.                 echo "<div id=\"consoleText\"><br/><h2>Text Analysis:</h2>";
  199.                 //Challenge 1
  200.                 echo "<br/><p>Words in text: " . $wordCount . "</p>";
  201.                
  202.                 //Challenge 2
  203.                 echo "<br/><p>Letters in text: " . $letterCount . "</p>";
  204.                
  205.                 //Challenge 3
  206.                 echo "<br/><p>Number of non-alphanumerics: " . $symbolCount . "</p>";
  207.                
  208.                 //Challenge 4
  209.                 echo "<br/><ol>Top 3 most common words:";
  210.                 //Determine the most-used words
  211.                 $sortedWordUse = $wordUse;
  212.                 rsort( $sortedWordUse );
  213.                 $sortedWordUse = array_unique( $sortedWordUse );
  214.                 $sortedWordUse = array_values( $sortedWordUse );
  215.                 for( $i = 0; $i < 3; $i++ ) {
  216.                     echo "<li>" . $sortedWordUse[$i] . " uses:<ul>";
  217.                     foreach( $allWords as $key => $value ) {
  218.                         if( $wordUse[$key] == $sortedWordUse[$i] ) {
  219.                             echo "<li>" . $value . "</li>";
  220.                         }
  221.                     }
  222.                     echo "</ul></li>";
  223.                 }
  224.                 echo "</ol>";
  225.                
  226.                 //Challenge 5
  227.                 echo "<br/><ol>Top 3 most common letters:";
  228.                 //Determine the most-used letters
  229.                 $sortedLetterUse = $letterUse;
  230.                 rsort( $sortedLetterUse );
  231.                 $sortedLetterUse = array_unique( $sortedLetterUse );
  232.                 $sortedLetterUse = array_values( $sortedLetterUse );
  233.                 for( $i = 0; $i < 3; $i++ ) {
  234.                     echo "<li>" . $sortedLetterUse[$i] . " uses:<ul>";
  235.                     foreach( $alphabet as $key => $value ) {
  236.                         if( $letterUse[$key] == $sortedLetterUse[$i] ) {
  237.                             echo "<li>" . $value . "</li>";
  238.                         }
  239.                     }
  240.                     echo "</ul></li>";
  241.                 }
  242.                 echo "</ol>";
  243.                
  244.                 //Optional 1
  245.                 echo "<br/><p>Most common first word of a paragraph:</p>";
  246.                 //Determine most common first words
  247.                 $max = 0;
  248.                 $index = 0;
  249.                 foreach( $psFrequency as $value ) {
  250.                     if( $value > $max ) {
  251.                         $max = $value;
  252.                     }
  253.                 }
  254.                 echo "<ul>Starts " . $max . " paragraphs:";
  255.                 foreach( $paragraphStarters as $key => $value ) {
  256.                     if( $psFrequency[$key] == $max ) {
  257.                         echo "<li>" . $value . "</li>";
  258.                     }
  259.                 }
  260.                 echo "</ul>";
  261.                 //Optional 2
  262.                 echo "<br/><table><tr><th colspan=5>Words used only once:</th></tr><tr>";
  263.                 $cells = 1;
  264.                 for( $i = 0; $i < count($allWords); $i++ ) {
  265.                     if( $wordUse[$i] == 1 ) {
  266.                         echo "<td>" . $allWords[$i] . "</td>";
  267.                         $cells += 1;
  268.                         if( $cells > 5 ) {
  269.                             echo "</tr><tr>";
  270.                             $cells = 1;
  271.                         }
  272.                     }
  273.                 }
  274.                 //Finish off last row
  275.                 while( $cells <= 5 ) {
  276.                     echo "<td></td>";
  277.                     $cells += 1;
  278.                 }
  279.                 echo "</tr></table>";
  280.                
  281.                 //Optional 3
  282.                 echo "<br/><ul>Alphanumerics not used:";
  283.                 for( $i = 0; $i < count($alphabet); $i++ ) {
  284.                     if( $letterUse[$i] == 0 ) {
  285.                         echo "<li>" . $alphabet[$i] . "</li>";
  286.                     }
  287.                 }
  288.                 echo "</ul>";
  289.                 echo "</div>";
  290.             }
  291.         }      
  292.        
  293.        
  294.     } else {
  295.         echo "<p>Please upload a text file to analyze.</p>";
  296.     }
  297. ?> 
  298.        
  299.     </div>
  300.     <div id="inputFormContainer">
  301.         <form action="./projects.php" method="post" id="inputForm" enctype="multipart/form-data">
  302.             <p>Enter text to analyze:</p>
  303.             <input type="file" name="inputFile" />
  304.             <input type="submit" name="submit" value="Submit" />
  305.         </form>
  306.     </div>
  307. </div>
  308. </body>
  309. </html>