如何生成随机数,而不纯批量脚本重复列表? [英] How to generate a list of random numbers without duplicates in pure batch scripting?

查看:193
本文介绍了如何生成随机数,而不纯批量脚本重复列表?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我要生成随机数以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 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

解决方案

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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆