Author Topic: WordCracker  (Read 8003 times)

0 Members and 1 Guest are viewing this topic.

Offline codeguy

  • Forum Regular
  • Posts: 174
Re: WordCracker
« Reply #30 on: October 08, 2018, 05:23:50 pm »
No, mine does unconditional permutations. Which is why it may have detected 3 more words than other submissions. But it does generate matches in lexical (alphabetical) order, saving sorting. For 8 characters or less, the speed is VERY similar to Steve's algorithm, running 8+ times to completion in the 5 second limit. Mine in 8 character mode, runs about .60s or less using the complete wordlist.txt document.

Offline SMcNeill

  • QB64 Developer
  • Forum Resident
  • Posts: 3972
    • Steve’s QB64 Archive Forum
Re: WordCracker
« Reply #31 on: October 08, 2018, 06:50:09 pm »
My entry into the field of long-arse string searches:

Code: QB64: [Select]
  1. SCREEN _NEWIMAGE(800, 600, 32)
  2. CONST In$ = "thequickbrownfoxjumpedoverthelazydogdreamingofcountingsheepthinkingofbrownfoxjumpingoverdogs"
  3.  
  4. InLen = LEN(in$)
  5.  
  6.  
  7. OPEN "WordList.txt" FOR BINARY AS #1
  8.     LINE INPUT #1, junk$
  9.     WordCount = WordCount + 1
  10.     IF LEN(junk$) > maxlength THEN maxlength = LEN(junk$)
  11. SEEK 1, 1
  12.  
  13. TYPE WordLetters
  14.     letter AS _UNSIGNED _BYTE
  15.     count AS _UNSIGNED _BYTE
  16. DIM Words(WordCount) AS STRING, Match(WordCount) AS LONG
  17. DIM WordLetters(WordCount, 26) AS WordLetters
  18. DIM Letters(97 TO 122) AS _UNSIGNED _BYTE
  19.  
  20. FOR i = 1 TO WordCount 'Load and prepare our word list and wordsearch array
  21.     LINE INPUT #1, Words(i)
  22.     FOR j = 1 TO LEN(Words(i))
  23.         a = ASC(Words(i), j)
  24.         IF a > 96 AND a < 123 THEN
  25.             afound = 0
  26.             FOR k = 1 TO WordLetters(i, 0).count
  27.                 IF a = WordLetters(i, k).letter THEN afound = k: EXIT FOR
  28.             NEXT
  29.             IF afound THEN
  30.                 WordLetters(i, afound).count = WordLetters(i, afound).count + 1 'add to the count of an existing letter
  31.             ELSE
  32.                 WordLetters(i, 0).count = WordLetters(i, 0).count + 1 'increase the total count of letters
  33.                 w = WordLetters(i, 0).count
  34.                 WordLetters(i, w).letter = a 'save the letter
  35.                 WordLetters(i, w).count = 1 'and count it 1 for the first time it appeared
  36.             END IF
  37.         ELSE
  38.             WordLetters(i, 0).count = 0 'invalidate words with non A-Z letters
  39.             EXIT FOR
  40.         END IF
  41.     NEXT
  42.  
  43. FOR i = 1 TO InLen 'get the letters for the search string
  44.     a = (ASC(in$, i) OR 32)
  45.     Letters(a) = Letters(a) + 1
  46.  
  47.  
  48. t# = TIMER
  49. DO UNTIL TIMER > t# + 5
  50.     loopcount = loopcount + 1
  51.     wordfound = 0 'reset our counter
  52.  
  53.     'THE MAIN SEARCH ROUTINE HERE
  54.  
  55.     FOR i = 1 TO WordCount 'now check every word for a match
  56.         sl = WordLetters(i, 0).count 'search limit
  57.         IF sl = 0 THEN GOTO invalid
  58.         FOR j = 1 TO sl
  59.             l = WordLetters(i, j).letter 'the letter in the word
  60.             IF Letters(l) < WordLetters(i, j).count THEN GOTO invalid 'it's impossible
  61.         NEXT
  62.         wordfound = wordfound + 1
  63.         Match(wordfound) = i
  64.         invalid:
  65.     NEXT
  66.  
  67.     'END OF THE MAIN SEARCH ROUTINE
  68.  
  69.  
  70. 'Print Results
  71. FOR i = 1 TO wordfound
  72.     PRINT Words(Match(i));
  73.     IF i < wordfound THEN PRINT ","; ELSE PRINT
  74. PRINT "DONE, with"; wordfound; "matches, with a speed of"; loopcount; "runs in 5 seconds."
  75.  
  76.  
  77. 'And, if you want to see the secret behind this method, here's how we store and retrieve our data:
  78.  
  79. FOR i = 1 TO 10 'I think just showing how we track 10 words should be fine enough
  80.     PRINT Words(i),
  81.     FOR j = 1 TO WordLetters(i, 0).count
  82.         PRINT CHR$(WordLetters(i, j).letter);
  83.         PRINT WordLetters(i, j).count;
  84.         PRINT ",";
  85.     NEXT
  86.     PRINT
  87.  
  88.  
  89. 'and here's the in$ and how its letter count holds up
  90.  
  91.  
  92. PRINT in$
  93. FOR i = 97 TO 122
  94.     PRINT Letters(i);
  95.  

Instead of 32-37 runs in 5 seconds, this does about 150 on my machine.   

If you're curious how it does it, remove the END statement and then let it run.  It'll show you how we basically break down our words so we never have to check the letters in them any more times than is absolutely necessary to make a match.  ;)
https://github.com/SteveMcNeill/Steve64 — A github collection of all things Steve!

Offline SMcNeill

  • QB64 Developer
  • Forum Resident
  • Posts: 3972
    • Steve’s QB64 Archive Forum
Re: WordCracker
« Reply #32 on: October 08, 2018, 07:30:11 pm »
And, a slight tweak to do some pre-sorting based on In$ size and non-A-Z characters, and to add a key$ to make certain that the words all contain a valid letter we designate, as per the original post's requirements:

Code: QB64: [Select]
  1. SCREEN _NEWIMAGE(800, 600, 32)
  2. CONST In$ = "thequickbrownfoxjumpedoverthelazydogdreamingofcountingsheepthinkingofbrownfoxjumpingoverdogs"
  3. 'CONST In$ = "abcdefghi"
  4. 'key$ = "a" 'make "" or remark this line out completely to do a search without a required key, as per the original post
  5. InLen = LEN(In$)
  6.  
  7.  
  8. OPEN "WordList.txt" FOR BINARY AS #1
  9.     LINE INPUT #1, junk$
  10.     WordCount = WordCount + 1
  11.     IF LEN(junk$) > maxlength THEN maxlength = LEN(junk$)
  12. SEEK 1, 1
  13.  
  14. TYPE WordLetters
  15.     letter AS _UNSIGNED _BYTE
  16.     count AS _UNSIGNED _BYTE
  17. DIM Words(WordCount) AS STRING, Match(WordCount) AS LONG
  18. DIM WordLetters(WordCount, 17) AS WordLetters
  19. DIM Letters(97 TO 122) AS _UNSIGNED _BYTE
  20.  
  21.  
  22. FOR i = 1 TO WordCount
  23.     wc = wc + 1
  24.     LINE INPUT #1, Words(wc)
  25.     IF LEN(Words(wc)) > InLen THEN 'remove words too long to fit
  26.         wc = wc - 1
  27.     ELSE
  28.         FOR j = 1 TO LEN(Words(wc)) 'remove non A-Z words as we're only searching for words with those letters
  29.             IF ASC(Words(wc), j) < 97 OR ASC(Words(wc), j) > 122 THEN wc = wc - 1: EXIT FOR
  30.         NEXT
  31.     END IF
  32. WordCount = wc
  33.  
  34. FOR i = 1 TO WordCount 'Load and prepare our word list and wordsearch array
  35.     FOR j = 1 TO LEN(Words(i))
  36.         a = ASC(Words(i), j)
  37.         afound = 0
  38.         FOR k = 1 TO WordLetters(i, 0).count
  39.             IF a = WordLetters(i, k).letter THEN afound = k: EXIT FOR
  40.         NEXT
  41.         IF afound THEN
  42.             WordLetters(i, afound).count = WordLetters(i, afound).count + 1 'add to the count of an existing letter
  43.         ELSE
  44.             WordLetters(i, 0).count = WordLetters(i, 0).count + 1 'increase the total count of letters
  45.             w = WordLetters(i, 0).count
  46.             WordLetters(i, w).letter = a 'save the letter
  47.             WordLetters(i, w).count = 1 'and count it 1 for the first time it appeared
  48.         END IF
  49.     NEXT
  50.  
  51. FOR i = 1 TO InLen 'get the letters for the search string
  52.     a = (ASC(In$, i) OR 32)
  53.     Letters(a) = Letters(a) + 1
  54.  
  55.  
  56. t# = TIMER
  57. DO UNTIL TIMER > t# + 5
  58.     loopcount = loopcount + 1
  59.     wordfound = 0 'reset our counter
  60.  
  61.     'THE MAIN SEARCH ROUTINE HERE
  62.  
  63.     FOR i = 1 TO WordCount 'now check every word for a match
  64.         sl = WordLetters(i, 0).count 'search limit
  65.         FOR j = 1 TO sl
  66.             l = WordLetters(i, j).letter 'the letter in the word
  67.             IF Letters(l) < WordLetters(i, j).count THEN GOTO invalid 'it's impossible
  68.         NEXT
  69.         IF key$ = "" THEN
  70.             wordfound = wordfound + 1
  71.             Match(wordfound) = i
  72.         ELSEIF INSTR(Words(i), key$) <> 0 THEN
  73.             wordfound = wordfound + 1
  74.             Match(wordfound) = i
  75.         END IF
  76.         invalid:
  77.     NEXT
  78.  
  79.     'END OF THE MAIN SEARCH ROUTINE
  80.  
  81.  
  82.  
  83. 'Print Results
  84. FOR i = 1 TO wordfound
  85.     PRINT Words(Match(i));
  86.     IF i < wordfound THEN PRINT ","; ELSE PRINT
  87. PRINT "DONE, with"; wordfound; "matches, with a speed of"; loopcount; "runs in 5 seconds."
  88.  
  89.  
  90.  
  91.  
  92.  
  93. 'And, if you want to see the secret behind this method, here's how we store and retrieve our data:
  94.  
  95. FOR i = 1 TO 10 'I think just showing how we track 10 words should be fine enough
  96.     PRINT Words(i),
  97.     FOR j = 1 TO WordLetters(i, 0).count
  98.         PRINT CHR$(WordLetters(i, j).letter);
  99.         PRINT WordLetters(i, j).count;
  100.         PRINT ",",
  101.     NEXT
  102.     PRINT
  103.  
  104.  
  105. 'and here's the in$ and how its letter count holds up
  106.  
  107.  
  108. PRINT In$
  109. FOR i = 97 TO 122
  110.     PRINT CHR$(i); LTRIM$(RTRIM$(STR$(Letters(i))));
  111.     IF i < 122 THEN PRINT ", "; ELSE PRINT

We now run nice and fast for both short and long strings.  We can use a preset qualifier key if we want to, but we don't have to.  Run times are ~900 loops for "abcdefghi" with a key of "a", and ~200 times with the long entry Bplus used in his test routine earlier.
https://github.com/SteveMcNeill/Steve64 — A github collection of all things Steve!

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
Re: WordCracker
« Reply #33 on: October 08, 2018, 07:34:55 pm »
Yah Steve, 140 loops on my machine fabulous. Poor Peter, you robbed him to pay Paul. ;-))
(Steve, this comment based on your previous code post, you posted another while I was getting list ready for codeguy.)

Hi code guy,

Here is my list of 392 words from stevemcneill from the given WordList.txt file posted earlier in thread.
Hope this helps you find differences in lists.

PS what is unconditional permutation?

* stevemcneill.txt (Filesize: 2.47 KB, Downloads: 221)
« Last Edit: October 08, 2018, 07:38:24 pm by bplus »

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
Re: WordCracker
« Reply #34 on: October 08, 2018, 07:59:49 pm »
Some time ago, I built a Word Search Solver and had thought about making a Word Search Puzzle Builder.

With this Word Crack code review, I am rethinking building a Word Search Puzzle Builder based on a longish quote. Hmm... a few more details to work out... but have good word list generator now and if you throw in allot of extra of the same letters, could be a quite a challenge, like getting a puzzle where all the pieces look the same.

Offline SMcNeill

  • QB64 Developer
  • Forum Resident
  • Posts: 3972
    • Steve’s QB64 Archive Forum
Re: WordCracker
« Reply #35 on: October 08, 2018, 08:19:52 pm »
And for those who are having trouble understanding how my last 2 examples work, the secret is in the letter counter.

Take APPLE as an example...  Instead of searching to see if the In$ has those 5 letters, we instead count the letters first, when we load the dictionary.  1 A, 2 P, 1 L, 1 E...    All we have to check is a maximum of 4 times, instead of 5; we just check to make certain In$ has 2 Ps in it once, rather than checking twice...

In some cases, this reduces a ton of letter checks.   MISSISSIPPI.  Instead of 11 letters, we check 4...   (1 M, 4 I, 4 S, 2 P).

Minimal conditional checking makes for maximum performance.  ;)
https://github.com/SteveMcNeill/Steve64 — A github collection of all things Steve!

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
Re: WordCracker
« Reply #36 on: October 08, 2018, 08:32:47 pm »
And for those who are having trouble understanding how my last 2 examples work, the secret is in the letter counter.

Take APPLE as an example...  Instead of searching to see if the In$ has those 5 letters, we instead count the letters first, when we load the dictionary.  1 A, 2 P, 1 L, 1 E...    All we have to check is a maximum of 4 times, instead of 5; we just check to make certain In$ has 2 Ps in it once, rather than checking twice...

In some cases, this reduces a ton of letter checks.   MISSISSIPPI.  Instead of 11 letters, we check 4...   (1 M, 4 I, 4 S, 2 P).

Minimal conditional checking makes for maximum performance.  ;)

PLUS, if you want to save even more time, save the processed Word List back into a new Data File, once and forever preprocessed!

Peter smiles, he ain't feel'in so broke no more.
« Last Edit: October 08, 2018, 08:34:16 pm by bplus »

Offline codeguy

  • Forum Regular
  • Posts: 174
Re: WordCracker
« Reply #37 on: October 08, 2018, 08:49:01 pm »
Unconditional permutation means I perform no checking as to whether the next generated permutation actually fits the pattern of the language. In essence, it will check for permutations of words beginning with rx or some other beginning consonant pair that does not appear in standard language. This is handy for finding abbreviations like RPM or GPS or even TLDR, which are not words in the standard sense, but is included in the English language as shorthand for Revolutions Per Minute Global Positioning System and Too Late Didn't READ. Even stuff like RTFM, whose translation I will leave to the reader. While my method is slow for very large strings, it is absolutely thorough and can work for languages that are not English too. Slow? Yes, it is slow, but it will not skip any possible permutations that could lead to missing words in a word list. This is why it's considered an exhaustive algorithm. Also, my method eliminates any chance for repetitions of words found. BTW, my name has 871 exactly matching words that are in wordlist.txt, among them. Sanhedrin, Idaho and ordinals. Weird, huh? But for words of 8 characters or less, using the permutation method and my searching algorithm is competitive to Steve's work. This word list does not contain axolotl, a kind of salamander (301 words in wordlist.txt), but 32 words contained in axolotl were found. With my algorithm, if it's in there, this will find it AND give results in sorted order.
« Last Edit: October 08, 2018, 09:09:56 pm by codeguy »

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
Re: WordCracker
« Reply #38 on: October 08, 2018, 09:05:36 pm »
Thanks codeguy,

As the man said, "Minimal conditional checking makes for maximum performance.  ;)  "

Oh hey, I've got try this with my middle name too, 1106! including roman, sagamen.

Offline SMcNeill

  • QB64 Developer
  • Forum Resident
  • Posts: 3972
    • Steve’s QB64 Archive Forum
Re: WordCracker
« Reply #39 on: October 08, 2018, 09:33:10 pm »
And for those who are having trouble understanding how my last 2 examples work, the secret is in the letter counter.

Take APPLE as an example...  Instead of searching to see if the In$ has those 5 letters, we instead count the letters first, when we load the dictionary.  1 A, 2 P, 1 L, 1 E...    All we have to check is a maximum of 4 times, instead of 5; we just check to make certain In$ has 2 Ps in it once, rather than checking twice...

In some cases, this reduces a ton of letter checks.   MISSISSIPPI.  Instead of 11 letters, we check 4...   (1 M, 4 I, 4 S, 2 P).

Minimal conditional checking makes for maximum performance.  ;)

PLUS, if you want to save even more time, save the processed Word List back into a new Data File, once and forever preprocessed!

Peter smiles, he ain't feel'in so broke no more.

If I were to save it as a processed list, I'd sort it first to put maximum letters first.

Apple has 2Ps and only one of every other letter.  Since double letters are rarer than single letters, if we check for the PP first, we're more likely to be able to skip the rest of the checks.

So, instead of 1A2P1L1E, I'd store it as 2P1A1E1L....

Take ELEVEN for a perfect example.  It's rare to see 4 Es in a word, but not so rare to find a single L, V, or N.  Check it first and chances are you can skip all the other letters completely.

***************

Edit: Scrabble letter values would actually be a good criteria for sorting order.  Z, X, Q at the front of the search list, A, E, I, O, U, S, T, and such as the last things compared.

I imagine you could eek out a considerable performance boost with minimal effort, implementing such a method.
« Last Edit: October 08, 2018, 09:36:42 pm by SMcNeill »
https://github.com/SteveMcNeill/Steve64 — A github collection of all things Steve!

Offline codeguy

  • Forum Regular
  • Posts: 174
Re: WordCracker
« Reply #40 on: October 08, 2018, 11:10:34 pm »
Steve, I was really impressed with your speedy performance, so I took the liberty of modifying it for exact same results and significantly faster performance.
Code: QB64: [Select]
  1.  
  2. SCREEN _NEWIMAGE(800, 600, 32)
  3. CONST In$ = "thequickbrownfoxjumpedoverthelazydogdreamingofcountingsheepthinkingofbrownfoxjumpingoverdogs"
  4. DIM wordcount AS LONG: wordcount = 0
  5. DIM maxlength AS LONG: maxlength = 0
  6. InLen = LEN(In$)
  7.  
  8.  
  9. OPEN "WordList.txt" FOR BINARY AS #1
  10.     LINE INPUT #1, junk$
  11.     wordcount = wordcount + 1
  12.     IF LEN(junk$) > maxlength THEN maxlength = LEN(junk$)
  13. SEEK 1, 1
  14.  
  15. TYPE WordLetters
  16.     letter AS _UNSIGNED _BYTE
  17.     count AS _UNSIGNED _BYTE
  18. DIM Words(wordcount) AS STRING, Match(wordcount) AS LONG
  19. DIM WordLetters(wordcount, 26) AS WordLetters
  20. DIM Letters(97 TO 122) AS _UNSIGNED _BYTE
  21. DIM KIterWordLettersCount AS LONG
  22. DIM afound AS LONG: afound = 0
  23. FOR i = 1 TO wordcount 'Load and prepare our word list and wordsearch array
  24.     LINE INPUT #1, Words(i)
  25.     FOR j = 1 TO LEN(Words(i))
  26.         ascii = ASC(Words(i), j)
  27.         SELECT CASE ascii
  28.             CASE 97 TO 122
  29.                 FOR KIterWordLettersCount = 1 TO WordLetters(i, 0).count
  30.                     IF ascii = WordLetters(i, KIterWordLettersCount).letter THEN afound = KIterWordLettersCount: EXIT FOR
  31.                 NEXT
  32.                 IF afound THEN
  33.                     WordLetters(i, afound).count = WordLetters(i, afound).count + 1 'add to the count of an existing letter
  34.                     afound = 0
  35.                 ELSE
  36.                     WordLetters(i, 0).count = WordLetters(i, 0).count + 1 'increase the total count of letters
  37.                     w = WordLetters(i, 0).count
  38.                     WordLetters(i, w).letter = ascii 'save the letter
  39.                     WordLetters(i, w).count = 1 'and count it 1 for the first time it appeared
  40.                 END IF
  41.             CASE ELSE
  42.                 WordLetters(i, 0).count = 0 'invalidate words with non A-Z letters
  43.                 EXIT FOR
  44.         END SELECT
  45.     NEXT
  46.  
  47. FOR i = 1 TO InLen 'get the letters for the search string
  48.     ascii = (ASC(In$, i) OR 32)
  49.     Letters(ascii) = Letters(ascii) + 1
  50.  
  51. DIM wordfound AS LONG
  52. t# = TIMER(.001)
  53. DO UNTIL TIMER > t# + 5
  54.     loopcount = loopcount + 1
  55.     wordfound = 0 'reset our counter
  56.  
  57.     'THE MAIN SEARCH ROUTINE HERE
  58.  
  59.     FOR i = 1 TO wordcount 'now check every word for a match
  60.         sl = WordLetters(i, 0).count 'search limit
  61.         IF sl THEN
  62.             FOR j = 1 TO sl
  63.                 l = WordLetters(i, j).letter 'the letter in the word
  64.                 IF Letters(l) < WordLetters(i, j).count THEN GOTO invalid 'it's impossible
  65.             NEXT
  66.             wordfound = wordfound + 1
  67.             Match(wordfound) = i
  68.         END IF
  69.         invalid:
  70.     NEXT
  71.  
  72.     'END OF THE MAIN SEARCH ROUTINE
  73.  
  74.  
  75. 'Print Results
  76. FOR i = 1 TO wordfound
  77.     PRINT Words(Match(i));
  78.     IF i < wordfound THEN PRINT ","; ELSE PRINT
  79. PRINT "DONE, with"; wordfound; "matches, with a speed of"; loopcount; "runs in 5 seconds."
  80.  
  81.  
  82. 'And, if you want to see the secret behind this method, here's how we store and retrieve our data:
  83.  
  84. FOR i = 1 TO 10 'I think just showing how we track 10 words should be fine enough
  85.     PRINT Words(i),
  86.     FOR j = 1 TO WordLetters(i, 0).count
  87.         PRINT CHR$(WordLetters(i, j).letter);
  88.         PRINT WordLetters(i, j).count;
  89.         PRINT ",";
  90.     NEXT
  91.     PRINT
  92.  
  93.  
  94. 'and here's the in$ and how its letter count holds up
  95.  
  96.  
  97. PRINT In$
  98. FOR i = 97 TO 122
  99.     PRINT Letters(i);
  100.  
  101.  
On my humble machine, this represents a 45 loops/5s to 80+ loops/5s. Awesome work, Steve.

Offline SMcNeill

  • QB64 Developer
  • Forum Resident
  • Posts: 3972
    • Steve’s QB64 Archive Forum
Re: WordCracker
« Reply #41 on: October 09, 2018, 12:13:36 am »
Thanks for the kind words, Codeguy.  ;)

I've worked with datasets like this thousands of times in the past, so I've learned a few tricks for making them run efficiently.  The above was "speedy enough" for most needs, but there's methods quite a bit faster we could employ -- if we wanted to put forth the effort and alter our data somewhat.

Absolute fastest method I can imagine is by dividing our data into a tree structure....

For example, let's start with this tree:

A
AA
AAA

The first 3 entries on our list are those three.  By "treeing" our data, we say, "If I don't have A in the search phrase, then I can't have anything below A"

Eliminate "A" and we eliminate EVERYTHING with an A.  Our search list just dropped 50k words.

If we have A, but not AA, we've eliminated all words with AA from our search list...

It's a "cascading elimination" scheme and it's efficient, and fast, as heck!

The main issue with it is generating the lookup table to begin with...  Your data would need to be stored in a similar manner to this:
A (the word), 52154 (number of words with this eliminator), 2,3,4,5,6.... (Word list)
AA (next word), 2154 (number of words with this eliminator), 3,44,67,87,... (Word list)

**********************

It would bloat our data file considerably, depending on how many "eliminators" we want to use (why use anything more than 2 digits?  Longer words get more unique, the longer they become.), but it'd reduce our list of possible words to check by huge chunks at a time...

Fastest method I can think of, at the moment anyway.  ;)

(And if you look at my previous code, you can see where I was already generating lists which we could use for elimination purposes for single letters back with the original code in message #18.)
« Last Edit: October 09, 2018, 12:18:44 am by SMcNeill »
https://github.com/SteveMcNeill/Steve64 — A github collection of all things Steve!

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
Re: WordCracker
« Reply #42 on: October 10, 2018, 01:39:23 pm »
This letter count number formula thing lends itself obviously to anagrams, so yesterday I started modifying the file with BFormulas  a 26 chr$() string of counts for a, b, c... and all day long as I proceeded through with code tests, I had strongest feeling of Deja Vu  that I had done this before, that we, Steve too, had worked through this before, probably at Walter's forum. I check through old code posts 3 times and do not find anything on Anagrams... so I keep going reluctantly because it becomes more and more clear we had done this before.

Finally late last night, I do find the old code posted under Rosetta Folder! Yes, that's right because it started from a challenge from Rosetta stuff we were doing. Dang! I failed to remember the biggest hint of all, to sort by the BFormula$ key. Man what a time saver it is doing it that way, like a blink of the eye!

So if you find a word in your name or you are word building from a string, every anagram of it is automatically included. So along with filing the WordList with the BFormula key at start for saving allot of time, some more time saving could be made by listing all the anagrams that come with such a BFormula! WordList was reduced by 6,500+ lines by listing anagrams. Can't wait to try timed tests for generating words lists.
« Last Edit: October 10, 2018, 01:51:28 pm by bplus »