난수를 생성하는 방법?


23

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

어떻게 할 수 있습니까?


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

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

답변:


20

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

유닉스 쉘 ( /bin/sh)

부름:

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

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

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, 같은 것 확인해야합니다 xrangerandom.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.