@West, @dabuek - I tried the approach of creating a number composed of primes for each dictionary word, and seeing if it divides cleanly into the equivalent number made up of the letter string provided… I would have expected it to be faster than my approach above, because once the numbers are calculated, it only has to do one division per word tested. But it seems to be about the same speed. And of course, it takes some time up front to calculate the numbers.
If you want to try it out…
This function calculates the number for each word in a list w, and returns a table with the corresponding numbers. I arranged letters by frequency to keep the numbers smaller and avoid overflow (I haven’t checked if there is any overflow).
function IndexWords(w)
local p={2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97,101}
chars=string.upper("etaoinsrhldcumfpgwybvkxjqz")
indexChar={}
for i=1,string.len(chars) do
indexChar[string.sub(chars,i,i)]=p[i]
end
local n={}
for i=1,#w do
local W=w[i]
local x=1
for j=1,string.len(W) do
local e=string.sub(W,j,j)
x=x*indexChar[e]
end
n[i]=x
end
print(n[#n])
return n
end
The function below finds the longest word matching a string of letters str, and prints it (as before, it assumes precalculation of a table LengthChange which contains the word count at the point where the length of the words increases (assuming they are sorted short to long).
function DoIndexed()
local str=string.upper(Letters)
if u<2 then print("too few letters") return end
if u>=9 then j=#WordList else j=LengthChange[u+1] end
local x=1
for j=1,string.len(str) do
local e=string.sub(str,j,j)
x=x*indexChar[e]
end
for i=j,1,-1 do
if math.fmod(x,index[i])==0 then print(WordList[i]) return end
end
print( "No words found")
end