乱数を生成する方法は?


23

新しい行で区切られた1つまたはいくつかの乱数を生成したいと思います。

これをどのように行うことができますか?


1
ピュアヴィム?または、:python?を使用して?
ムル

純粋なvimが推奨されますが、組み込みではない場合は、覚えやすい簡単な方法であれば問題ありません。
ケノーブ

回答:


20

このための組み込み機能はないため、外部の何かを使用する必要があります。

UNIXシェル(/bin/sh

呼び出し:

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

with 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スクリプトはPythonスクリプトよりも一般的であるように思われるため、Rubyがおそらく次に最適な選択肢です。乱数の取得は簡単です:

:ruby puts Random.rand(10)

または、15個の数字を取得するには:

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

Python

ランダムモジュールを使用できます。単一の番号を取得するには:

: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 '...'")(これには、ruby / pythonがインストールされている必要があります。


の代わりにtr -d '[:space:]'、おそらくtr -cd '[:digit:]'grepフィルターのために?
ムル

@muru私はそれは私がそれを使用しなかった理由OPが....尋ねたように...あなたはまた、改行することにより、この方法を区切って番号を取得されOSX上で動作するかわからない
マーティンTournoij

その場合は...。GNUはBSDに勝ります。:P
ムル

シェル(システム)を使用して乱数を入力することもでき: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ソリューションです。私は作成しませんでした。CharlesE. 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をPythonでコンパイルしている場合、次のメソッドは行の末尾にランダムな数字を追加します。

: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をインストールするか%RANDOM%Carpetsmokerが示唆する変数を使用する必要があります。

回避策としてシェルとPythonにアクセスできない場合は、現在のタイムスタンプの最後の数桁を使用します。次に例を示します。

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

注:非常に頻繁に使用する場合は、を実行する単純な関数を作成してくださいreturn reltimestr(reltime())[-4:]

注:上記のメソッドは、暗号化キーの生成に使用すべきではない擬似乱数整数のみを返します。


さらに乱数を追加するに@:は、を押してコマンドを繰り返してください。または10@:、新しい行で区切られたより多くの乱数を追加するには、数字のプレフィックス(など)を付けます。


関連:


それはまたで動作しますzshが、ないとshdashfishcsh、またはtcsh...あなたが使用することができます:r! bash -c 'echo $RANDOM'...
マーティンTournoij

「現在のタイムスタンプから最後の数桁を返す」 ->これはランダムではありません。時間を使用して擬似乱数を取得することは、暗号化以外の目的であっても、ほとんど常に悪い考えです。タイムスタンプの解像度が秒単位で、「file。$ random」を1秒間に2回作成するとどうなりますか?おっとっと!...さらに、GetRandom()良いprng 重要な場合に誰かがあなたの関数をいつ使用するかわからないので、可能であれば最初から正しくすることをお勧めます(そして、ほとんど常にここで可能です!)
Martin Tournoij

私は品質がわからない$RANDOMが、これが悪いPRNGである場合、それはさらに悪いPRNGを使用する理由ではない:-)代わりに、より良いPRNGにアップグレードしてください!私の知る限り、一般的に利用可能な/dev/urandomすべてのプラットフォームでbash利用できるため、使用しない理由はわかりません。
マーティントゥルノイ

1
私は知りませんでした$RANDOM。@Carpetsmokerが指摘しているように、「貧乏人のRNG」かもしれませんが、それは@kenorb(質問をした人)の「簡単に覚えやすい」という要件に間違いなく適合しています。
ダルカー

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、文字列のリストであり、我々はそれを我々がPythonで希望の方法を文字列のリストを割り当てることができます。random.samplePythonでランダムな整数のリストを取得するために考えられる最も簡単な方法です。


@Carpetsmoker は、random.samplePython 2の2つの引数のみを返しstrます。これは、文字列に変換する組み込み関数です。Py3の同等物を調べてみましょう(str同じで、確認する必要がxrangeありますrandom.sample
ムル

@Carpetsmoker aargh、タイプミス。60の後のブラケットは10000の後にあるはずです。またxrange、Python3にはありません。これrangeは同等であるためです(rangePy2 とは異なり、実際にはリストを構築しません)。
ムル

@Carpetsmokerそして最後の違いはmap、Py3でリストではなく反復可能を返すため、最後の行が使用されることですlist(map(str, random.sample(range(10000), 60)))
-muru

さて、私はいくつかの(マイナー)とあなたの投稿を編集する自由を撮影した両方のPython 2と3 ...と互換性を持たせるために変更
マーティンTournoij
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.