난수를 생성하는 방법?


23

줄 바꿈으로 구분 된 하나 또는 몇 개의 난수를 생성하고 싶습니다.

어떻게 할 수 있습니까?


1
순수한 Vim? 또는 :python?
— muru

순수한 vim이 선호되지만 내장되어 있지 않으면 기억하기 쉬운 방법이 좋습니다.
— kenorb

답변:


20

이를위한 내장 기능이 없으므로 외부에서 무언가를 사용해야합니다.

유닉스 쉘 ( /bin/sh)

부름:

strings -n 1 < /dev/urandom | tr -d '[:space:]' | head -c15

와 system()좋은 방법입니다. 다음 tr과 grep같이 바꾸면 숫자 만 얻을 수 있습니다 .

strings -n 1 < /dev/urandom | grep -o '[[:digit:]]' | head -c15

Vim에서 이것을 다음과 같이 사용할 수 있습니다.

:echo system("strings -n 1 < /dev/urandom | grep -o '[[:digit:]]'  | head -c15")

숫자 15는 원하는 숫자의 양입니다 (적절하게 조정). 이것은 Linux, BSD, OSX 및 기타 UNIX 시스템에서 작동해야합니다. MS Windows에서는 작동하지 않습니다.

또한 내 웹 로그 게시물 " 명령 줄에서 비밀번호 생성 "을 참조하십시오 (여기에 대한 많은 나쁜 해결책이 있습니다).

루비

루비 스크립팅은 파이썬 스크립팅보다 조금 더 일반적이기 때문에 루비가 아마도 최선의 선택입니다. 난수를 얻는 것은 쉽다 :

:ruby puts Random.rand(10)

또는 15 개의 숫자를 얻으려면 :

:ruby 15.times { puts Random.rand(10) }

파이썬

임의 모듈을 사용할 수 있습니다 . 단일 번호를 얻으려면 :

:py import random; print(random.randint(0, 9))

또는 15 자리 숫자 :

:py import random
:py for i in range(0, 15): print(random.randint(0, 9))

이것은 Python 2와 3 모두에서 작동합니다.

Windows PowerShell

Get-Random 임의의 숫자를 얻는 데 사용할 수 있습니다 .

:echo system('Get-Random')

윈도우 cmd.exe

Windows 7 이상은 PowerShell과 함께 제공되어야하지만 최대의 호환성을 원하면을 사용할 수 있습니다 cmd.exe. 특별한 변수가 있습니다 %RANDOM%:

:echo system('@echo %RANDOM%')

참고 : 이것은 매우 무작위가 아닙니다! , 시간을 사용합니다 (!)


Ruby 또는 Python 솔루션을 사용하기 위해 Ruby 또는 Python 바인딩을 사용할 필요는 없습니다. 별도의 스크립트를 작성하여 호출 할 수도 있습니다 system("python -c '...'")(이것은 분명히 루비 / 파이썬이 설치되어 있어야합니다).


대신 tr -d '[:space:]', 아마도 tr -cd '[:digit:]'은 grep 필터?
— muru

@muru OSX에서 작동하는지 잘 모르겠습니다. 이것이 제가 사용하지 않은 이유입니다. OP와 같은 방법으로 개행 문자로 숫자를
— 구분할 수도 있습니다

그렇다면 ... GNU가 BSD를 능가합니다. : P
— muru

또한 임의의 숫자를 입력하기 위해 쉘 (시스템)을 사용할 수 있습니다. 즉 :r! hexdump -n $((3*4)) -e '"%d"' /dev/urandom, 3 개의 임의 부호있는 정수를 생성합니다.
— HAL 9001

1
@kenorb 이것은 3 개의 부호있는 임의의 정수를 입력하기 위해 셸을 올바르게 사용합니다.:r! hexdump -n $((3*4)) -e '"\%d\n"' /dev/urandom
— HAL 9001

12

여기에 순수한 vimscript 솔루션이 있습니다. 나는 그것을 만들지 않았다, 그것은 Charles E. Campbell에 의해 개발되었다. 당신은 자신의 코드와 Github에서의 환매 특약 찾을 수 있습니다 여기를 .


이 알고리즘은 Vim 시작시 생성 된 3 개의 시드를 사용하고 시드에 적용된 계산 및 순열을 기반으로 의사 난수를 생성합니다.

" Randomization Variables
" with a little extra randomized start from localtime()
let g:rndm_m1 = 32007779 + (localtime()%100 - 50)
let g:rndm_m2 = 23717810 + (localtime()/86400)%100
let g:rndm_m3 = 52636370 + (localtime()/3600)%100

변수 범위는 생성기 함수에서 사용되기 때문에 전역으로 선언되지만 스크립트 ( s:) 로 제한 될 수 있습니다.

그리고 여기 발전기 기능이 있습니다 :

function! Rndm()
    let m4= g:rndm_m1 + g:rndm_m2 + g:rndm_m3
    if( g:rndm_m2 < 50000000 )
        let m4= m4 + 1357
    endif
    if( m4 >= 100000000 )
        let m4= m4 - 100000000
        if( m4 >= 100000000 )
            let m4= m4 - 100000000
        endif
    endif
    let g:rndm_m1 = g:rndm_m2
    let g:rndm_m2 = g:rndm_m3
    let g:rndm_m3 = m4
    return g:rndm_m3
endfun

리포지토리에는 다음 기능이 포함됩니다.

  • 종자의 "무작위"초기화;
  • 텍스트 파일에서 일부 사용자 정의 시드를 읽는 방법.
  • 의사 랜덤 생성기
  • 몇 가지 임의의 기능 :
    • 범위 내에서 난수를 생성하는 함수
    • 주사위 롤링 기능
    • 순차적 인 정수 목록을 무작위로 바꾸는 함수

다음은 생성기를 테스트하기 위해 작성한 빠른 테스트입니다. 0에서 9 사이의 1000000 개의 숫자를 생성하고 각 숫자의 발생 횟수를 세었습니다. 결과는 다음과 같습니다.

0 : 100409
1 : 99435
2 : 100433
3 : 99578
4 : 100484
5 : 99948
6 : 100394
7 : 99649
8 : 99803
9 : 99867

보시다시피 세대는 잘 분산되어있는 것 같습니다. 나는 이것이 무작위 생성기를 테스트하기에 충분하지 않다는 것을 알고 있으므로 자유 시간이 있으면 추가 분석을 시도합니다.


7

이 방법은에서 찾을 수있다 VIM-randomtag 플러그인, 당신은 그냥 할 때 읽기 ... 현재 시간의 마이크로 것은, 가능한가에 기반이되는 몇 가지 수를, 당신은 많은 임의성 품질에 대해 걱정하거나, 보안 문제 등이없는 :

function! s:randnum(max) abort
  return str2nr(matchstr(reltimestr(reltime()), '\v\.@<=\d+')[1:]) % a:max
endfunction

4

Vim은 네이티브 랜덤 제너레이터를 제공하지 않지만, 만약 당신이 파이썬으로 컴파일 한 vim을 가지고 있다면, 다음 메소드는 라인 끝에 임의의 숫자를 추가합니다 :

:py import vim, random; vim.current.line += str(random.randint(0, 9))

참고 : vim이 Python을 지원하는지 확인하려면 다음을 시도하십시오 :echo has('python')(예 : 1).

또한 $RANDOM의사 난수 (0-32767)를 반환하는 변수 (bash / ksh / zsh와 함께 작동) 를 제공하는 쉘을 사용할 수도 있습니다 .

:r! echo $RANDOM

또는:

:put =system('echo $RANDOM')

또는:

:r! od -An -td -N1 /dev/urandom

Windows에서는 Cygwin / MSYS / SUA가 설치되어 있거나 Carpetsmoker가 제안한 %RANDOM%대로 변수를 사용해야 합니다 .

해결 방법과 같이 셸 및 Python에 액세스 할 수없는 경우 현재 타임 스탬프의 마지막 몇 자리를 사용합니다 (예 :

:put =reltimestr(reltime())[-2:]

참고 : 자주 사용하는 경우 간단한 기능을 작성하십시오 return reltimestr(reltime())[-4:].

참고 : 위의 메소드는 암호화 키를 생성하는 데 사용해서는 안되는 의사 난수 만 반환합니다.


더 많은 난수를 추가하려면을 눌러 @:명령을 다시 반복하십시오. 또는 숫자 (예 :)를 사용 10@:하여 새 줄로 구분 된 훨씬 많은 난수를 추가하십시오.


관련 :


또한 작동 zsh하지만,하지와 sh, dash, fish, csh, 또는 tcsh... 당신은 사용할 수 있습니다 :r! bash -c 'echo $RANDOM'...
— 마틴 Tournoij에게

"현재 타임 스탬프에서 마지막 몇 자리를 반환" -> 이것은 무작위가 아닙니다. 의사 난수를 얻기 위해 시간을 사용하는 것은 암호화가 아닌 목적으로 도 거의 항상 나쁜 생각 입니다. 타임 스탬프의 해상도가 초 단위이고 "file. $ random"을 1 초에 두 번 만들면 어떻게됩니까? 죄송합니다! ... 게다가, 누군가가 GetRandom()언제 좋은 prng 가 중요한지 당신의 기능을 언제 사용할 것인지 알지 못합니다. 가능하면 처음부터 바로 사용 하는 것이 좋습니다 (그리고 거의 항상 가능합니다!)
— Martin Tournoij

나는 품질이 무엇인지 모르지만 이것이 $RANDOMPRNG가 불량한 경우 더 나쁜 PRNG를 사용하는 이유는 아닙니다 :-) 대신, 더 나은 PRNG로 업그레이드하십시오! 내가 아는 한, 일반적으로 사용 가능한 /dev/urandom모든 플랫폼에서 bash사용할 수 있으므로 사용하지 않는 이유는 없습니다 .
— Martin Tournoij

1
에 대해 몰랐습니다 $RANDOM. 아주 멋진 작은 도구 인 것 같지만 "Carpetsmoker가 지적한 것처럼"가난한 사람 RNG "일지라도"쉽게 기억할 수있는 "의 @kenorb (질문을 한 사람) 요구 사항에 꼭 맞습니다.
— Dalker

4

Vim 바이너리에 패치 8.1.2342가 포함되어 있으면 rand()및 srand()기능을 사용할 수 있습니다 .


예를 들어, 개행으로 구분 된 10 개의 난수를 생성하려면 다음을 수행하십시오.

let seed = srand()
echo range(10)->map({-> rand(g:seed)})->join("\n")

100보다 낮은 10 개의 난수를 생성하려면 :

let seed = srand()
echo range(10)->map({-> rand(g:seed) % 100})->join("\n")

5 자로 된 10 개의 무작위 알파벳 문자열을 생성하려면 다음을 수행하십시오.

let seed = srand()
echo range(10)
   \ ->map({-> range(5)
   \           ->map({-> (97+rand(g:seed) % 26)->nr2char()})->join('')})
   \ ->join("\n")

사전 파일에서 가져온 10 개의 임의 단어를 생성하려면 다음을 수행하십시오 /usr/share/dict/words.

let seed = srand()
let words = readfile('/usr/share/dict/words')
let len = len(words)
echo range(10)->map({-> g:words[rand(g:seed) % g:len]})->join("\n")

5 개의 임의 단어로 구성된 10 개의 시퀀스를 생성하려면

let seed = srand()
let words = readfile('/usr/share/dict/words')
let len = len(words)
echo range(10)
   \ ->map({-> range(5)
   \           ->map({-> g:words[rand(g:seed) % g:len]})->join()})
   \ ->join("\n")

임의의 UUID 버전 4를 생성하려면 다음을 수행하십시오.

" Based on this answer: /programming//a/38191078/9780968
let seed = srand()
let random_numbers = range(30)->map({-> rand(g:seed) % 16})
echo call('printf', ['%x%x%x%x%x%x%x%x-%x%x%x%x-4%x%x%x'] + random_numbers[:14])
 \ ..call('printf', ['-X%x%x%x-%x%x%x%x%x%x%x%x%x%x%x%x'] + random_numbers[15:])
 \   ->substitute('X', '89ab'[rand(seed) % 4], '')

임의의 색 구성표를 적용하려면

let seed = srand()
let colorschemes = getcompletion('', 'color')
let len = colorschemes->len()
exe 'colo '..colorschemes[rand(seed) % len]

3

Vimscript에는 임의의 숫자에 대한 기본 함수가 없다고 생각합니다.

사용 방법 :python(아마도 10000과 60을 매개 변수로 대체하여 함수에서 사용) :

:python <<EOF
import vim
import random

line = vim.current.window.cursor[0]
r = getattr(__builtins__, 'xrange', range) # To make it work for both Python 2 & 3
vim.current.buffer[line:line] = list(map(str, random.sample(r(10000), 60)))
EOF

Vim의 Python 스크립팅에 대한 빠른 소개를 보려면 python 을 통해 vim에서 상자 만들기에 대한 답변을 참조하십시오 .

vim.current.buffer문자열 목록 이기 때문에 파이썬에서와 같이 문자열 목록을 할당 할 수 있습니다. random.sample파이썬에서 임의의 정수 목록을 얻는 가장 간단한 방법입니다.


@Carpetsmoker random.sample는 Python 2에서 두 가지 인수 만 repuires합니다 str. 사물을 문자열로 변환하는 내장 함수입니다. 저합니다 (Py3 등가물을 살펴 보자 str, 같은 것 확인해야합니다 xrange과 random.sample).
— muru

@Carpetsmoker 아아, 오타. 60 이후의 대괄호는 10000 이후입니다. 그리고 xrange파이썬 3 range에는 해당하지 않습니다 ( rangePy2 와 달리 실제로 목록을 구성하지는 않습니다 ).
— muru

@Carpetsmoker 그리고 마지막 차이점은 mapPy3에서 iterable을 반환하지만리스트는 반환하지 않는다는 것입니다. 마지막 줄은list(map(str, random.sample(range(10000), 60)))
— muru

자, 저는 파이썬 2와 3 모두와 호환되도록 약간의 (사소한) 변경으로 게시물을 편집 할 자유를 얻었습니다.
— Martin Tournoij
당사 사이트를 사용함과 동시에 당사의 쿠키 정책과 개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.