I want to generate a list of random numbers with a predefined number of items %RND_TOTAL%
in the given range from %RND_MIN%
to %RND_MAX%
and with a certain interval %RND_INTER%
. Of course this can be accomplished with the following code snippet:
@echo off
setlocal EnableExtensions EnableDelayedExpansion
rem total number of random numbers:
set /A "RND_TOTAL=8"
rem range for random numbers (minimum, maximum, interval):
set /A "RND_MIN=1, RND_MAX=10, RND_INTER=1"
rem loop through number of random numbers:
for /L %%I in (1,1,%RND_TOTAL%) do (
rem compute a random number:
set /A "RND_NUM[%%I]=!RANDOM!%%((RND_MAX-RND_MIN)/RND_INTER+1)*RND_INTER+RND_MIN"
echo !RND_NUM[%%I]!
)
endlocal
exit /B
Here is an example of the corresponding output (4
and 9
both apear twice here):
2 4 9 8 9 4 7 3
But how can I create such a list without any duplicate items?
Of course I could use the following script which checks each item whether it is already avalable in the array-like variable RND_NUM[]
, but this approach is quite inefficient due to nested for /L
loops and, particularly when %RND_TOTAL%
comes close to the available count of random numbers covered by the the range specification, due to numerous calculation repetitions:
@echo off
setlocal EnableExtensions EnableDelayedExpansion
rem total number of random numbers, duplicate flag (`0` means no duplicates):
set /A "RND_TOTAL=20, FLAG_DUP=0"
rem range for random numbers (minimum, maximum, interval):
set /A "RND_MIN=1, RND_MAX=30, RND_INTER=1"
rem loop through number of random numbers, generate them in a subroutine:
for /L %%I in (1,1,%RND_TOTAL%) do (
call :SUB %%I
echo !RND_NUM[%%I]!
)
endlocal
exit /B
:SUB
rem get number of already collected random numbers:
set /A "RND_COUNT=%1-1"
:LOOP
rem compute a random number:
set /A "RND_NUM[%1]=!RANDOM!%%((RND_MAX-RND_MIN)/RND_INTER+1)*RND_INTER+RND_MIN"
rem check whether random number appears in the previous collection:
if %FLAG_DUP% EQU 0 (
for /L %%I in (1,1,%RND_COUNT%) do (
rem re-compute random number if duplicate has been encountered:
if !RND_NUM[%1]! EQU !RND_NUM[%%I]! (
goto :LOOP
)
)
)
exit /B
This is the related sample output (no duplicates here):
4 1 2 10 6 7 3 5
Aucun commentaire:
Enregistrer un commentaire