How to generate a list of random numbers without duplicates in pure batch scripting?

前端 未结 5 1951
青春惊慌失措
青春惊慌失措 2020-12-07 03:51

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%

5条回答
  •  醉酒成梦
    2020-12-07 04:14

    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[
    

提交回复
热议问题