I believe this is the ultimate optimized solution for native batch - even faster than Aacini's 2nd solution.
There is no preprocessing, other than to put dot space at the front of the list, and space dot at the end.
It uses line continuation (escaping the end-of-line) to insert a newline character before the desired word.
@echo off
setlocal EnableDelayedExpansion
:: The list must start with dot space and end with space dot, the word order does not matter
set "list=. daddy day gladly happily key pay randomly ray say urgency utility yesterday ."
:start
echo(
:: Exit if list is empty
if "%list: =%" equ ".." (
echo No more words in list
exit /b
)
:: Get the user's input, exit if none
set "INPUTWORD="
set /p "INPUTWORD=>Enter a word: "
if not defined INPUTWORD exit /b
:: Get the last letter of input
set "LastLetter=%INPUTWORD:~-1%"
:: Iterate value of list after replacing "<space>%LastLetter%" with "<newLine>%LastLetter%".
:: Skip the first line and take the first token, which will be myWord.
:: If no substitution, then only one line so DO will not fire.
:: The empty line below (after the FOR line) is critical - DO NO REMOVE
for /f "usebackq skip=1" %%W in ('!list: %LastLetter%^=^
%LastLetter%!') do (
REM remove myWord from the list
set "list=!list: %%W = !"
REM show result and loop back for more (breaks out of loop)
echo myWord = %%W
goto :start
)
:: Only reaches here if myWord not found
echo myWord not found
goto :start
UPDATE
Inspired by Aacini, I did some timing tests of our optimised methods. We are really talking about splitting hairs :-)
Here are the final results:
dbenham Aacini
----------- -----------
Preprocess the list: 2.00 msec 104.00 msec
One input & lookup: 2.91 msec 2.82 msec
The only significant difference is in the preprocessing, but even that is probably meaningless as far as user experience.
Below is my testing methodology:
I removed all comments and restructured the code a bit to make sure both do the same amount of work and give the same result.
I rigged up a list of 728 words (no longer ending in "y", but that shouldn't really matter). I also rigged up an input file with 551 words, one per line, including a last "word" consisting of a period so that it excercises the "word not found" branch.
I save the "my word" output of both scripts and compare to show they produce identical results.
dbenham.bat
@echo off
setlocal EnableDelayedExpansion
:: Define list
set "base=andy bay cay daddy day easy fly gladly happily inky jay key lay may nay ornery pray quay randomly ray say truancy urgency vacancy way xray yesterday zesty "
for %%L in (a b c d e f g h i j k l m n o p q r s t u v w x y z) do set "list=!list! !base: =%%L !"
:: Measure preprocessing time
set t1_0=%time%
set "list=.!list!."
set t1_1=%time%
:: Measure lookup time
set /a cnt=0
set "t2_0=%time%"
:start
echo(
set "INPUTWORD="
set /p "INPUTWORD=>Enter a word: "
if not defined INPUTWORD goto :done
set /a cnt+=1
set "LastLetter=%INPUTWORD:~-1%"
for /f "usebackq skip=1" %%W in ('!list: %LastLetter%^=^
%LastLetter%!') do (
set "list=!list: %%W = !"
echo My word = %%W
goto start
)
echo My word not found in list
goto start
:done
set "t2_1=%time%"
call :elapsed t1_0 t1_1 t1
call :elapsed t2_0 t2_1 t2
>&2 echo Preprocessing time for 728 words = %t1%0 msec
>&2 echo Lookup time for %cnt% inputs = %t2%0 msec
exit /b
:elapsed t1 t2 rtn
setlocal
for /f "tokens=1-8 delims=:., " %%a in ("!%~1: =0! !%~2: =0!") do (
set /a "t1=(((1%%a*60)+1%%b)*60+1%%c)*100+1%%d-36610100, t2=(((1%%e*60)+1%%f)*60+1%%g)*100+1%%h-36610100, tDiff=t2-t1"
)
if !tDiff! lss 0 set /a tDiff+=24*60*60*100
endlocal & set "%~3=%tDiff%"
exit /b
Aacini.bat
@echo off
setlocal EnableDelayedExpansion
:: Define list
set "base=andy bay cay daddy day easy fly gladly happily inky jay key lay may nay ornery pray quay randomly ray say truancy urgency vacancy way xray yesterday zesty "
for %%L in (a b c d e f g h i j k l m n o p q r s t u v w x y z) do set "list=!list! !base: =%%L !"
:: Measure preprocessing time
set "t1_0=%time%"
for %%w in (%list%) do (
set "word=%%w"
for /F %%l in ("!word:~0,1!") do set "subList[%%l]=!subList[%%l]! %%w"
)
set "t1_1=%time%"
:: Measure lookup time
set /a cnt=0
set "t2_0=%time%"
:START
echo(
set "INPUTWORD="
set /p "INPUTWORD=>Enter a word: "
if not defined INPUTWORD goto :done
set /a cnt+=1
set lastLetter=%INPUTWORD:~-1%
if defined subList[%lastLetter%] (
for /F "tokens=1*" %%a in ("!subList[%lastLetter%]!") do (
echo My word = %%a
set "subList[%lastLetter%]=%%b"
)
) else (
echo My word not found in list
)
goto START
:done
set "t2_1=%time%"
call :elapsed t1_0 t1_1 t1
call :elapsed t2_0 t2_1 t2
>&2 echo Preprocessing time for 728 words = %t1%0 msec
>&2 echo Lookup time for %cnt% inputs = %t2%0 msec
exit /b
:elapsed t1 t2 rtn
setlocal
for /f "tokens=1-8 delims=:., " %%a in ("!%~1: =0! !%~2: =0!") do (
set /a "t1=(((1%%a*60)+1%%b)*60+1%%c)*100+1%%d-36610100, t2=(((1%%e*60)+1%%f)*60+1%%g)*100+1%%h-36610100, tDiff=t2-t1"
)
if !tDiff! lss 0 set /a tDiff+=24*60*60*100
endlocal & set "%~3=%tDiff%"
exit /b
-- Test run results --
D:\test>dbenham <test.txt >dbenham.txt
Preprocessing time for 728 words = 10 msec
Lookup time for 551 inputs = 1610 msec
D:\test>dbenham <test.txt >dbenham.txt
Preprocessing time for 728 words = 00 msec
Lookup time for 551 inputs = 1600 msec
D:\test>dbenham <test.txt >dbenham.txt
Preprocessing time for 728 words = 00 msec
Lookup time for 551 inputs = 1610 msec
D:\test>dbenham <test.txt >dbenham.txt
Preprocessing time for 728 words = 00 msec
Lookup time for 551 inputs = 1590 msec
D:\test>dbenham <test.txt >dbenham.txt
Preprocessing time for 728 words = 00 msec
Lookup time for 551 inputs = 1620 msec
D:\test>aacini <test.txt >aacini.txt
Preprocessing time for 728 words = 100 msec
Lookup time for 551 inputs = 1600 msec
D:\test>aacini <test.txt >aacini.txt
Preprocessing time for 728 words = 110 msec
Lookup time for 551 inputs = 1540 msec
D:\test>aacini <test.txt >aacini.txt
Preprocessing time for 728 words = 90 msec
Lookup time for 551 inputs = 1560 msec
D:\test>aacini <test.txt >aacini.txt
Preprocessing time for 728 words = 110 msec
Lookup time for 551 inputs = 1580 msec
D:\test>aacini <test.txt >aacini.txt
Preprocessing time for 728 words = 110 msec
Lookup time for 551 inputs = 1580 msec
D:\test>fc dbenham.txt aacini.txt
Comparing files dbenham.txt and AACINI.TXT
FC: no differences encountered
I averaged the 5 timings for each script, and divided the lookup time by 551 to get the time for one iteration.