如何生成随机数,而不纯批量脚本重复列表? [英] How to generate a list of random numbers without duplicates in pure batch scripting?
问题描述
我要生成随机数以predefined项目在给定的范围从%RND_MIN号
到%RND_TOTAL%
列表%%RND_MAX%
,并用一定的时间间隔%RND_INTER%
。当然这可以用下面的code片段来完成:
关闭@echo
SETLOCAL ENABLEEXTENSIONS EnableDelayedExpansion
REM随机数的总数:
设置/ ARND_TOTAL = 8
REM范围的随机数(最小值,最大值,区间):
设置/ ARND_MIN = 1,RND_MAX = 10,RND_INTER = 1
通过随机数的数REM循环:
对/ L %%我在(1,1,%RND_TOTAL%)做(
REM计算一个随机数:
设置/ ARND_NUM [%% i] =!RANDOM!%%((RND_MAX-RND_MIN)/ RND_INTER + 1)* RND_INTER + RND_MIN
回音!RND_NUM [%% I]!
)
ENDLOCAL
出口/ B
下面是相应的输出( 4
和 9
这两个apear这里两次)的例子:
2
4
9
8
9
4
7
3
块引用>但我怎么能创建这样一个列表的没有任何重复的项目
当然,我可以使用下面的脚本,它会检查每个项目无论是已经在阵列样可变
RND_NUM []
可采用,但这种做法是相当低效的原因嵌套为/ L
循环和,特别是当%RND_TOTAL%
接近所涵盖的随机数的可用计数该范围内的规范,由于大量的重复计算:关闭@echo
SETLOCAL ENABLEEXTENSIONS EnableDelayedExpansion
REM随机数的总数,重复标志(`0`装置无重复):
设置/ ARND_TOTAL = 20,FLAG_DUP = 0
REM范围的随机数(最小值,最大值,区间):
设置/ ARND_MIN = 1,RND_MAX = 30,RND_INTER = 1
REM遍历随机数的数,产生它们的子程序:
对/ L %%我在(1,1,%RND_TOTAL%)做(
拨打:SUB %%我
回音!RND_NUM [%% I]!
)
ENDLOCAL
出口/ B:SUB
REM获得已收集的随机数数:
设置/ ARND_COUNT = 1-1%
:循环
REM计算一个随机数:
设置/ ARND_NUM [%1] =!RANDOM!%%((RND_MAX-RND_MIN)/ RND_INTER + 1)* RND_INTER + RND_MIN
REM检查随机数是否出现在previous集合:
如果%FLAG_DUP%EQU 0(
对/ L %%我在(1,1,%RND_COUNT%)做(
REM重新计算,如果已经遇到重复的随机数:
如果!RND_NUM [%1]! EQU!RND_NUM [%% I]! (
后藤:LOOP
)
)
)
出口/ B这是有关样本输出(在这里没有重复):
4
1
2
10
6
7
3
五
块引用>解决方案我稍微修改了code我写了前段时间:
关闭@echo
SETLOCAL EnableDelayedExpansionREM随机数的总数:
设置/ ARND_TOTAL = 8
REM范围的随机数(最小,最大):
设置/ ARND_MIN = 1,RND_MAX = 10设置/ A系列= RND_MAX-RND_MIN + 1REM创建在给定范围内的所有号码输入列表
设置输入=
对/ L %% i的(%RND_MIN%,1%RND_MAX%)做(
设置输入=!输入!%%我
)
设置输入=%输入%
回声:[%输入%]从输入列表中以随机顺序物权提取RND_TOTAL元素
集产量
对/ L %% i的(%RND_TOTAL%, - 1,1)做(
设置/ ArandIndex =(!随机!*范围)/ 32768 + 1,增程= 1
来电:MoveInputToOutput randIndex!
)
回声OUT:[%输出%]GOTO:EOF:MoveInputToOutput randIndex
FOR / F令牌=%1%% n的(%输入%),做(
组输出=%输出%%% n和
设置输入=输入:%% N =!
)
出口/ B输出例如:
>测试
中:[1 2 3 4 5 6 7 8 9 10]
OUT:[8 7 9 3 1 4 5 2]>测试
中:[1 2 3 4 5 6 7 8 9 10]
OUT:9 2 6 4 8 5 1]>测试
中:[1 2 3 4 5 6 7 8 9 10]
OUT:1 2 4 3 8 5 7 9]对不起,但我不明白什么
%RND_INTER%
值用于...修改:使用该
%RND_INTER%
价值和产生的随机数的数量都没有限制新版关闭@echo
SETLOCAL EnableDelayedExpansionREM随机数的总数:
设置/ ARND_TOTAL = 8
REM范围的随机数(最小值,最大值,区间):
设置/ ARND_MIN = 1,RND_MAX = 10,RND_INTER = 1REM创建在给定范围内的所有号码输入向量
设置的n = 0
对/ L %% i的(%RND_MIN%,%RND_INTER%,%RND_MAX%)做(
集/ A N + = 1
设置,在[!N!= %%我
)
回声输入:
设置[
回声/从输入向量以随机顺序物权提取RND_TOTAL元素
对/ L %%我在(1,1,%RND_TOTAL%)做(
设置/ ArandIndex =(!随机!* N)/ 32768 + 1
集/ A出[%% i]于=!randIndex!],在[!randIndex!=在[!N!],正= 1
)
回声输出:
出发[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
and9
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 nestedfor /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
解决方案I slightly modified a code I wrote some time ago:
@echo off setlocal EnableDelayedExpansion rem total number of random numbers: set /A "RND_TOTAL=8" rem range for random numbers (minimum, maximum): set /A "RND_MIN=1, RND_MAX=10" set /A "range=RND_MAX-RND_MIN+1" rem Create an input list with all numbers in given range set "input=" for /L %%i in (%RND_MIN%,1,%RND_MAX%) do ( set "input=!input! %%i" ) set "input=%input% " echo IN: [%input%] rem Extract RND_TOTAL elements from input list in random order set "output=" for /L %%i in (%RND_TOTAL%,-1,1) do ( set /A "randIndex=(!random!*range)/32768+1, range-=1" call :MoveInputToOutput !randIndex! ) echo OUT: [%output%] goto :EOF :MoveInputToOutput randIndex for /F "tokens=%1" %%n in ("%input%") do ( set output=%output% %%n set input=!input: %%n = ! ) exit /B
Output example:
> test IN: [ 1 2 3 4 5 6 7 8 9 10 ] OUT: [ 8 7 9 3 1 4 5 2] > test IN: [ 1 2 3 4 5 6 7 8 9 10 ] OUT: [ 9 2 10 6 4 8 5 1] > test IN: [ 1 2 3 4 5 6 7 8 9 10 ] OUT: [ 1 2 4 3 8 5 7 9]
Excuse me, but I don't understand what
%RND_INTER%
value is used for...EDIT: New version that use the
%RND_INTER%
value and have not limit in the number of random numbers generated.@echo off setlocal 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 Create an input vector with all numbers in given range set "n=0" for /L %%i in (%RND_MIN%,%RND_INTER%,%RND_MAX%) do ( set /A n+=1 set "in[!n!]=%%i" ) echo Input: set in[ echo/ rem Extract RND_TOTAL elements from input vector in random order for /L %%i in (1,1,%RND_TOTAL%) do ( set /A "randIndex=(!random!*n)/32768+1" set /A "out[%%i]=in[!randIndex!], in[!randIndex!]=in[!n!], n-=1" ) echo Output: set out[
这篇关于如何生成随机数,而不纯批量脚本重复列表?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!