Comment detail

重複無し乱数 (Nested Flatten)
バッチで書いてみました。27行目の行末に半角空白が 1つあるので注意してください。

環境変数%RANDOM%は 0~32767の範囲で乱数を返します。乱数値の一桁目( 0~9)だけを採用
し、要素数 nで除算すると剰余は 0~n-1のいずれかの値になります。その値を擬似配列の
インデックスとして利用するため、値に 1を加えて補正しています。シャッフルに偏りが
生じるとは思いますが、これが考えつく限界でした。

  e.g.
    C:\>bingo 10
    [ 10, 4, 9, 3, 1, 8, 7, 6, 2, 5 ]

    C:\>bingo 3
    [ 2, 1, 3 ]

    C:\>bingo 3
    [ 2, 3, 1 ]

    C:\>bingo 3
    [ 2, 1, 3 ]

    C:\>bingo 10
    [ 1, 7, 10, 5, 6, 4, 8, 2, 9, 3 ]

遅延環境変数展開と環境変数%RANDOM%を利用しているので、Windows NTでは動作しません。
Windows XPで動作を確認。
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
:: bingo.bat
@echo off
  setlocal enabledelayedexpansion
    set i=0
    set j=0
    set t=
    set v=0

    echo %1|findstr /r "[^0-9]" >NUL 2>&1
    if %ERRORLEVEL% equ 0 (echo %0 [NUMBER] & goto :EOF)

    :: 擬似配列を生成
    for /l %%i in (1,1,%1) do set v_%%i=%%i

    :: 値をシャッフル
    set i=1
    :loop
      set /a j=%RANDOM:~-1%%%%1+1
      set v=!v_%i%!
      set v_%i%=!v_%j%!
      set v_%j%=%v%
      set /a i+=1
    if %i% lss %1 goto loop

    for /l %%i in (1,1,%1) do (
      set t=!t!!v_%%i!
      if %%i lss %1 set t=!t!, 
    )
  endlocal & echo [ %t% ]
goto :EOF
引数( n)の桁数に応じて、乱数値から切り出す桁数を変えました。 nの値が大きい場合の
偏りは軽減されたものの、ソースの見通しは悪くなったかもしれません。

  e.g.
    5a6
    >     set l=0
    15a17,18
    >     call :length %1 l
    >     echo set j=%%RANDOM:~-%l%%%>_.bat
    17,18c20,23
    <     :loop
    <       set /a j=%RANDOM:~-1%%%%1+1
    ---
    >     :shuffle
    >       ::  8進数として解釈されないよう 0を加算
    >       call _.bat & set /a j+=0
    >       set /a j=%j%%%%1+1
    23c28,29
    <     if %i% lss %1 goto loop
    ---
    >     if %i% lss %1 goto shuffle
    >     del _.bat
    31a38,50
    > :length
    >   setlocal
    >     set i=0
    >     set t=%1
    >     set t=%t:"=%
    > 
    >     :loop
    >       set t=%t:~1%
    >       set /a i+=1
    >     if not "%t%" == "" goto loop
    >   endlocal & set %2=%i%
    > goto :EOF

# 小数が扱えないのは痛いなぁ...

Index

Feed

Other

Link

Pathtraq

loading...