Rasgele sayılar nasıl oluşturulur?


23

Yeni satırla ayrılmış bir veya birkaç rasgele sayı üretmek istiyorum.

Bu nasıl yapılabilir?


1
Saf vim? Ya da, demek :python?
muru

Saf vim tercih etti, ancak eğer yerleşik değilse, akılda kalıcı olan herhangi bir yöntem iyidir.
kenorb

Yanıtlar:


20

Bunun için yerleşik bir tesis bulunmadığından harici bir şey kullanmanız gerekir.

UNIX Kabuğu ( /bin/sh)

Arayan:

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

ile system()iyi bir yoldur. Sen değiştirerek yalnızca rakamlardan alabilirsiniz trile grep:

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

Bunu Vim'de şu şekilde kullanabilirsiniz:

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

15 sayısı, istediğiniz sayı miktarıdır (buna göre ayarlayın). Bu Linux, BSD, OSX ve diğer UNIX sistemlerinde çalışmalıdır. MS Windows'ta çalışmaz.

Ayrıca " Komut satırından şifreleri oluştur " web günlüğüme bakın (bunun için birçok kötü çözüm var).

Yakut

Ruby muhtemelen bir sonraki en iyi seçimdir, çünkü Ruby scriptleri Python scriptlerinden biraz daha yaygın görünmektedir. Rasgele bir sayı elde etmek kolaydır:

:ruby puts Random.rand(10)

Veya 15 numara almak için:

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

piton

Rasgele modülü kullanabilirsiniz ; Tek bir numara almak için:

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

Veya 15 numara:

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

Bu, hem Python 2 & 3 için çalışmalı.

Windows PowerShell

Get-Random Rasgele bir sayı almak için kullanabilirsiniz :

:echo system('Get-Random')

, Windows cmd.exe

Windows 7 ve sonraki sürümleri PowerShell ile birlikte gönderilmelidir, ancak maksimum uyumluluk istiyorsanız, kullanabilirsiniz cmd.exe. Özel bir değişkeni var %RANDOM%:

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

Not: Bu çok rastgele değil! , zaman kullanır (!)


Ruby veya Python çözümlerini kullanmak için Ruby veya Python ciltlerini kullanmanız gerekmediğini unutmayın; Ayrıca ayrı bir komut dosyası oluşturabilir ve bunları arayabilir system("python -c '...'")(bu ruby ​​/ python'un yüklü olduğunu gerektirir).


Yerine tr -d '[:space:]', belki tr -cd '[:digit:]'grep filtresi için?
muru

@muru OSX üzerinde çalışacağından emin değilim, bu yüzden kullanmamıştım ... Ayrıca OP'nin sorduğu gibi yeni bir
hatla

Durum buysa ... GNU BSD'yi yener. : P
muru,

Biri ayrıca kabuğu (sistem) rasgele sayıları girmek için kullanabilir, yani :r! hexdump -n $((3*4)) -e '"%d"' /dev/urandom3 rastgele işaretlenmiş tam sayı üretebilir.
HAL 9001,

1
: @kenorb Bu, doğru 3 imza rasgele tamsayılar girmek için kabuk kullanır:r! hexdump -n $((3*4)) -e '"\%d\n"' /dev/urandom
HAL 9001

12

İşte saf bir vimscript çözümü. Yaratmadım, Charles E. Campbell tarafından geliştirildi. Burada Github deposunu koduyla birlikte bulabilirsiniz .


Algoritma, Vim başlangıcında üretilen 3 tohum kullanır ve tohumlara uygulanan hesaplamaları ve permütasyonları temel alan sahte rastgele bir sayı üretir:

" 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

Değişkenler kapsamı global olarak bildirilir, çünkü bunlar jeneratör işlevi tarafından kullanılırlar, ancak komut dosyası ( s:) ile sınırlandırılabilirler.

Ve işte jeneratör işlevi:

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

Depo aşağıdaki işlevleri içerir:

  • Tohumların bir "rastgele" başlatılması;
  • Kullanıcı tanımlı bazı tohumları bir metin dosyasından okumanın bir yolu;
  • Bir sözde rasgele jeneratör
  • Birkaç rastgele fonksiyon:
    • Bir aralıkta rastgele sayı üreten bir işlev
    • Bir zar haddeleme işlevi
    • Sıralı tamsayıların listesini rastgele değiştiren bir işlev

Jeneratörü test etmek için yazdığım hızlı bir test: 0 ile 9 arasında 1000000 sayı ürettim ve her sayının oluşum sayısını saydım.

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

Gördüğünüz gibi nesiller iyi dağılmış gibi görünüyor. Bunun rastgele bir oluşturucuyu test etmek için yeterli olmadığının farkındayım, bu yüzden biraz boş zamanım varsa ekstra analiz yapmaya çalışacağım.


7

Bu, vim-randomtag eklentisinde bulunan ve şu anki mikrosaniye okumaya dayanan, sadece bir sayıyı istediğinizde kullanabileceğiniz , rastgelelik kalitesi ile ilgilenmediğiniz veya güvenlik kaygılarınız vb. İle ilgilenmediğiniz bir yöntemdir.

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

4

Vim yerel rastgele üreteci sunmuyor, ancak Python ile derlenmiş bir vim kullanıyorsanız, aşağıdaki yöntem satırınızın sonuna rastgele bir rakam ekleyecektir:

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

Not: Vim'inizin Python'u destekleyip desteklemediğini kontrol etmek için şunları deneyin: :echo has('python')(evet için 1).

Bir $RANDOMdeğişken (örneğin bash / ksh / zsh ile birlikte çalışan) bir takma ad (0-32767) döndüren kabuk sunan da kullanabilirsiniz :

:r! echo $RANDOM

veya:

:put =system('echo $RANDOM')

veya:

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

Windows'ta, Cygwin / MSYS / SUA'nın kurulu olması veya Carpetsmoker'in önerdiği şekilde %RANDOM%değişken kullanmanız gerekir .

Kabuk ve Python'a erişiminiz yoksa, geçici çözüm için olduğu gibi, geçerli zaman damgasındaki son birkaç basamağı kullanırsınız, örneğin:

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

Not: Çok sık kullanıyorsanız, olacak basit bir fonksiyon yazın return reltimestr(reltime())[-4:].

Not: Yukarıdaki yöntemlerde yalnızca bir şifreleme anahtarı oluşturmak için kullanılmaması gereken bir sahte tamsayı döndürülür.


Daha fazla rasgele numara eklemek için, lütfen @:komutu tekrarlamak için basın . Veya 10@:yeni satırlarla ayrılan çok daha fazla rasgele sayı eklemek için sayı (benzeri ) ile ön ek girin .


İlgili:


Ayrıca çalışır zsh, ancak birlikte sh, dash, fish, csh, veya tcsh... Sen kullanabilirsiniz :r! bash -c 'echo $RANDOM'...
Martin Tournoij

"Geçerli zaman damgasındaki son birkaç haneyi döndür" -> Bu rastgele değil. Sözde rasgele bir sayı elde etmek için zaman kullanmak, kripto dışı amaçlar için bile , neredeyse her zaman kötü bir fikirdir . Zaman damgasının çözünürlüğü saniyeler içinde ise ve saniyede iki kez "dosya. $ Random" oluşturursanız ne olur? Hata! ... Artı, asla birilerinin sizin kullanmayı giderken bilmek GetRandom()iyi prng işlevini yapar sadece başından mümkünse onu almak daha iyidir, böylece madde (ve burada hemen hemen her zaman mümkündür!)
Martin Tournoij

Kalitesinin ne olduğunu bilmiyorum $RANDOM, ama eğer bu zayıf bir PRNG ise, o zaman daha da zayıf bir PRNG kullanmak için bir neden değildir :-) Bunun yerine, daha iyi bir PRNG'ye yükseltin! Gibi bildiğim kadarıyla, /dev/urandombütün platformlarda kullanılabilir bashı için bir neden görmüyorum bu yüzden, yaygın kullanılabilir değil kullanabilirsiniz.
Martin Tournoij

1
Bilmiyordum $RANDOM. Çok hoş küçük bir araç gibi görünüyor ve bir "fakir adamın RNG'si" olsa bile (@Carpetsmoker'ın işaret ettiği gibi), kesinlikle "kenorb'un (soruyu soran)" kolayca unutulmaz "şartına uyuyor.
Dalker

4

Vim binary'inizin 8.1.2342 yamasını içermesi koşuluyla rand()ve srand()işlevlerini kullanabilirsiniz .


Örnek olarak, yeni satırlarla ayrılmış 10 rasgele sayı oluşturmak için:

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

100'den aşağı 10 rasgele sayı üretmek için:

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

5 karakterden oluşan 10 rasgele alfabetik dizge oluşturmak için:

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

10 rastgele kelime üretmek için (sözlük dosyasından alınmıştır /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 rastgele sözcüğün 10 dizisini oluşturmak için:

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")

Rasgele bir UUID sürüm 4 oluşturmak için:

" 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], '')

Rasgele bir renk şeması uygulamak için:

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

3

Vimscript'te rastgele sayılar için yerel bir işlev olduğunu sanmıyorum.

Kullanmanın bir yolu :python(belki 10000 ve 60 ile değiştirilen bir fonksiyonda kullanın):

: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'deki Python komut dizisine hızlı bir giriş yapmak için, Vim'deki bir kutu python aracılığıyla yapma konusundaki cevabımı görün .

Yana vim.current.bufferdizeleri listesidir, biz buna Python'da açar gibi dizeleri listesini atayabilirsiniz. random.samplePython'da rastgele tamsayıların listesini almak için düşünebildiğim en basit yol.


@Carpetsmoker random.sample, Python 2'deki sadece iki argümanı onarır, strşeyleri dizgelere dönüştüren yerleşik işlevdir. Py3 eşdeğerlerini aramama izin ver ( straynı olurdu, kontrol etmek zorunda kalacak xrangeve random.sample).
muru

@Carpetsmoker aargh, yazım hatası. 60'tan sonra parantezin 10000'den sonra olduğu varsayılır. Ve xrangePython3'te değildir, çünkü rangeeşdeğerdir (aslında rangePy2'dekilerin aksine bir liste de oluşturmaz).
muru

@Carpetsmoker Ve son fark, mapPy3'te yinelenebilir ve bir liste değil, son satırın kullanmasıdırlist(map(str, random.sample(range(10000), 60)))
muru

Tamam, mesajınızı Python 2 ve 3 ile uyumlu hale getirmek için bazı (küçük) değişikliklerle düzenleme özgürlüğünü aldım ...
Martin Tournoij
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.