//letterSetList = {"abcdefl", "aeiouys", "stpcdei", "eiaornt", "uyozxqj"}; /* Craige Hales answer 1apr2020 https://community.jmp.com/t5/JMP-Challenge/JMP-scripting-challenge/ba-p/255434 Challenge by Don McCormack "I love a good word puzzle. This challenge is inspired by Spelling Bee in The New York Times. In it, you must create words from a list of seven letters with the condition that one of the letters is always used. The other letters can be used once, more than once, or not at all. I am modifying the conditions to make things a bit trickier. Given seven letters, find: 1) The longest word using all seven letters and only those seven letters. Letters may be used more than once. 2) The longest word using all seven letters and any other letters. 3) The longest word using all seven letters and any other letters where no letter from the set of seven is used more than once. 4) The longest word in which 5 of the 7 letters appears. Any letter including those outside of the 7 may appear once or more except the two unused letters from the list of 7, which may not appear at all. For all four items, there may be no words that meet the criteria or multiple words. Scripts must accept a list of seven lower case alphabetical character (a-z) strings that will be stored in a global variable named letterSetList. For example, if the first item in the list is "abcdefl", the answers would be: "defaceable" "discomfortableness" "fibrochondrosteal" "formaldehydesulphoxylate" and "scientificophilosophical" All scripts will be tested on the same three seven-letter sets. All words will be taken from the dictionary posted below. Please access it as a JMP data table when your script executes. Write all words to the log. Make sure to include the item number with the output. You will have a time limit of five minutes total. Entries must be received by 11:59 PM Eastern Time on Wednesday, April 15. " */ start0=tickseconds(); // the data table load is not in the individual times, just the total // download the dictionary if it is not already in the temp directory /* If( !File Exists( "$temp/challengedictionary.jmp" ), global:dictionary = Open( "https://community.jmp.com/kvoqx44227/attachments/kvoqx44227/jmp-challenge-blog/1/1/Word List.jmp" ); global:dictionary << save( "$temp/challengedictionary.jmp" ); , global:dictionary = Open( "$temp/challengedictionary.jmp", invisible ) ); */ //global:dictionary = Data Table("Word List"); dictionary = Data Table("Word List"); // forget the data table. Make a string of words separated by spaces list = dictionary:words << getvalues; string = Concat Items( list, " " ); // count the letter frequencies - this code was needed to get the string below... /* counts=[=>0]; patmatch(string,patrepeat(" "|(patlen(1)>>c+pattest(counts[c]+=1,1))+patfence())); chars=counts<1, for(i=1,i<=nitems(list) & (i==1 | length(list[i])==length(list[i-1])), i+=1, write(" ",list[i]); ) , write(" *none*") ) ); for(itest=1,itest<=nitems(letterSetList),itest+=1, start1=tickseconds(); test = letterSetList[itest]; // grab the letters for this run from the list at the top write("\!n\!nTest letters: ",test); // arrange the test letters in order of frequency by removing everything else test = Regex( frequent, "[^" || test || "]", "", GLOBALREPLACE ); // fortunately the alphabet is limited so we can create the list of letters that // are not in the set and use it with span rather than using notany which is slower excluded = regex( "abcdefghijklmnopqrstuvwxyz","[" || test || "]", "", GLOBALREPLACE ); If( Length( test ) != 7, Throw( "test set must be 7 characters" ) ); mat = J( 7, 1, 0 );// accumulators candidate1 = {""}; candidate2 = {""}; candidate3 = {""}; candidate4 = {""}; // pre-build the pattern as an expression that will have strings coded into it for speed // key1...key7 are replaced with the frequent-sorted letters and others with the // excluded letters. The expression matches a single word with a space before it. // the first word does not have 5 different letters so could never participate. // mat is a matrix that counts the occurrences of the 7 letters. When the repeat // can't go further (hits space or end) the pattest that categorizes the word // uses mat and others to determine which list to add the word. The words are // added at the front if they are at least as long as the previous front word. grabword = Expr( " " + // the first word "aalii" matches no rule and the blank is found after it Pat Test( others = mat[0] = 0; 1 ) + (// re-init accumulators Pat Repeat( (Pat Span( other ) + Pat Test( others = 1; 1 )) | // most likely first (key1 + Pat Test( mat[1] += 1; 1 )) | // (key2 + Pat Test( mat[2] += 1; 1 )) | // (key3 + Pat Test( mat[3] += 1; 1 )) | // (key4 + Pat Test( mat[4] += 1; 1 )) | // (key5 + Pat Test( mat[5] += 1; 1 )) | // (key6 + Pat Test( mat[6] += 1; 1 )) | // (key7 + Pat Test( mat[7] += 1; 1 )) ) // ) >> word + Pat Test( // categorize this word smat=Sum( mat ); if(smat>=5, present = mat >= 1; npresent = Sum( present ); If( (npresent == 7), if(length(word)>=length(candidate2[1]),Insert Into( candidate2, word, 1 )); If( !others, if(length(word)>=length(candidate1[1]),Insert Into( candidate1, word, 1 )); ); If( smat == 7, if(length(word)>=length(candidate3[1]),Insert Into( candidate3, word, 1 )); );, (npresent == 5), if(length(word)>=length(candidate4[1]),Insert Into( candidate4, word,1 )); ) ); 1 // pattest result ) // ); // fix up the expression with data for the placeholders; a variable // won't be consulted later Substitute Into( grabword, Expr( key1 ), Substr( test, 1, 1 ) ); Substitute Into( grabword, Expr( key2 ), Substr( test, 2, 1 ) ); Substitute Into( grabword, Expr( key3 ), Substr( test, 3, 1 ) ); Substitute Into( grabword, Expr( key4 ), Substr( test, 4, 1 ) ); Substitute Into( grabword, Expr( key5 ), Substr( test, 5, 1 ) ); Substitute Into( grabword, Expr( key6 ), Substr( test, 6, 1 ) ); Substitute Into( grabword, Expr( key7 ), Substr( test, 7, 1 ) ); Substitute Into( grabword, Expr( other ), excluded ); grabword = Eval( grabword ); // finish building the grabword pattern // do all the work. The first patbreak is skipping to the space after the first // word. adding a space at the beginning of the string would also work, but it // adds 0.1 second because the string is long. rc = Pat Match( string, Pat Break( " " ) + Pat Repeat( grabword + Pat Fence() ) + Pat R Pos( 0 ) ); if(!rc,throw("Pat match failed")); // wrapping up a single set of characters f("Rule1(only those 7, all of them)",candidate1); f("Rule2(all 7 and any others also)",candidate2); f("Rule3(all 7 no repeats + others)",candidate3); f("Rule4(exactly 5 of 7 and others)",candidate4); stop1=tickseconds(); show(stop1-start1); // about 2 sec ); // really wrapping up stop0=tickseconds(); write("\!n\!nTotal time"); show(stop0-start0); // about 10 sec for 5 tests /* typical run: Test letters: abcdefl Rule1(only those 7, all of them) defaceable Rule2(all 7 and any others also) discomfortableness Rule3(all 7 no repeats + others) fibrochondrosteal Rule4(exactly 5 of 7 and others) scientificophilosophical formaldehydesulphoxylate stop1 - start1 = 1.71666666667443; Test letters: aeiouys Rule1(only those 7, all of them) *none* Rule2(all 7 and any others also) thymolsulphonephthalein pancreaticoduodenostomy formaldehydesulphoxylic Rule3(all 7 no repeats + others) nonunderstandingly Rule4(exactly 5 of 7 and others) thyroparathyroidectomize scientificophilosophical pathologicopsychological stop1 - start1 = 2.18333333331975; Test letters: stpcdei Rule1(only those 7, all of them) epideistic Rule2(all 7 and any others also) pseudolamellibranchiate pericardiomediastinitis pancreaticoduodenostomy Rule3(all 7 no repeats + others) pseudohallucinatory Rule4(exactly 5 of 7 and others) tetraiodophenolphthalein pathologicopsychological formaldehydesulphoxylate stop1 - start1 = 1.96666666667443; Test letters: eiaornt Rule1(only those 7, all of them) interattrition anterointerior Rule2(all 7 and any others also) tetraiodophenolphthalein Rule3(all 7 no repeats + others) misadventurously Rule4(exactly 5 of 7 and others) formaldehydesulphoxylate stop1 - start1 = 2.53333333332557; Test letters: uyozxqj Rule1(only those 7, all of them) *none* Rule2(all 7 and any others also) *none* Rule3(all 7 no repeats + others) *none* Rule4(exactly 5 of 7 and others) hydroxyanthraquinone benzofuroquinoxaline stop1 - start1 = 1.14999999999418; Total time stop0 - start0 = 9.66666666665697; */