Làm thế nào để tạo số ngẫu nhiên?


23

Tôi muốn tạo một hoặc một vài số ngẫu nhiên cách nhau bởi dòng mới.

Làm thế nào điều này có thể được thực hiện?


1
Tinh khiết vim? Hoặc, nói, sử dụng :python?
muru 14/2/2015

Pure vim ưa thích, nhưng nếu nó không tích hợp, bất kỳ phương pháp dễ nhớ nào cũng được.
kenorb

Câu trả lời:


20

Không có tiện ích tích hợp cho việc này, vì vậy bạn sẽ cần sử dụng một cái gì đó bên ngoài.

UNIX Shell ( /bin/sh)

Gọi điện thoại:

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

với system()là một cách tốt. Bạn chỉ có thể nhận được các số bằng cách thay thế trbằng grep:

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

Bạn có thể sử dụng điều này trong Vim như vậy:

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

Số 15 là số lượng bạn muốn (điều chỉnh cho phù hợp). Điều này sẽ hoạt động trên Linux, BSD, OSX và các hệ thống UNIX khác. Nó sẽ không hoạt động trên MS Windows.

Cũng xem bài đăng trên web của tôi " Tạo mật khẩu từ dòng lệnh " (có rất nhiều giải pháp tồi cho việc này).

Hồng ngọc

Ruby có lẽ là sự lựa chọn tốt nhất tiếp theo, vì kịch bản lệnh Ruby dường như phổ biến hơn một chút so với kịch bản Python. Lấy một số ngẫu nhiên rất dễ dàng:

:ruby puts Random.rand(10)

Hoặc để có được 15 số:

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

Con trăn

Bạn có thể sử dụng mô-đun ngẫu nhiên ; để có được một số duy nhất:

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

Hoặc 15 số:

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

Điều này sẽ làm việc cho cả Python 2 & 3.

Windows PowerShell

Bạn có thể sử dụng Get-Random để có được một số ngẫu nhiên:

:echo system('Get-Random')

các cửa sổ cmd.exe

Windows 7 trở lên sẽ xuất xưởng với PowerShell, nhưng nếu bạn muốn tương thích tối đa, bạn có thể sử dụng cmd.exe. Nó có một biến đặc biệt %RANDOM%:

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

Lưu ý: Điều này không phải là rất ngẫu nhiên! , nó sử dụng thời gian (!)


Lưu ý rằng bạn không cần sử dụng các liên kết Ruby hoặc Python để sử dụng các giải pháp Ruby hoặc Python; bạn cũng có thể tạo một tập lệnh riêng và gọi chúng bằng system("python -c '...'")(điều này đòi hỏi ruby ​​/ python được cài đặt, rõ ràng.


Thay vì tr -d '[:space:]', có lẽ tr -cd '[:digit:]'cho bộ lọc grep?
muru

@muru Tôi không chắc rằng nó sẽ hoạt động trên OSX, đó là lý do tại sao tôi không sử dụng nó ... Bạn cũng nhận được các số được phân tách bằng một dòng mới theo cách này, như OP đã hỏi ....
Martin Tournoij

Nếu đó là trường hợp .... GNU đánh bại BSD. : P
muru 14/2/2015

Người ta cũng có thể sử dụng shell (hệ thống) để nhập số ngẫu nhiên, nghĩa là :r! hexdump -n $((3*4)) -e '"%d"' /dev/urandomsẽ tạo ra 3 số nguyên được ký ngẫu nhiên.
HAL 9001

1
@kenorb Điều này sẽ sử dụng chính xác trình bao để nhập 3 số nguyên ngẫu nhiên đã ký::r! hexdump -n $((3*4)) -e '"\%d\n"' /dev/urandom
HAL 9001

12

Đây là một giải pháp vimscript tinh khiết . Tôi đã không tạo ra nó, nó được phát triển bởi Charles E. Campbell. Bạn có thể tìm thấy một repo Github với mã của mình ở đây .


Thuật toán sử dụng 3 hạt giống được tạo khi khởi động Vim và tạo số giả ngẫu nhiên dựa trên các tính toán và hoán vị áp dụng cho các hạt giống:

" 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

Phạm vi biến được khai báo là toàn cục vì chúng được sử dụng bởi hàm tạo nhưng nó có thể bị giới hạn ở tập lệnh ( s:)

Và đây là chức năng tạo:

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

Repo bao gồm các chức năng sau:

  • Một khởi tạo "ngẫu nhiên" của hạt giống;
  • Một cách để đọc một số hạt giống do người dùng định nghĩa từ một tệp văn bản;
  • Một máy phát ngẫu nhiên giả
  • Một số chức năng ngẫu nhiên:
    • Hàm tạo số ngẫu nhiên trong phạm vi
    • Một chức năng lăn xúc xắc
    • Một hàm để hoán đổi ngẫu nhiên một danh sách các số nguyên tuần tự

Đây là một bài kiểm tra nhanh mà tôi đã viết để kiểm tra trình tạo: Tôi đã tạo ra 1000000 số trong khoảng từ 0 đến 9 và đếm số lần xuất hiện của mỗi số ở đây là kết quả:

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

Như bạn có thể thấy thế hệ dường như được phân phối tốt. Tôi biết rằng điều này phần lớn không đủ để kiểm tra một trình tạo ngẫu nhiên nên tôi sẽ cố gắng thực hiện một số phân tích bổ sung nếu tôi có thời gian rảnh.


7

Đây là một phương pháp được tìm thấy trong plugin vim-Randomtag , dựa trên việc đọc ... micro giây thời gian hiện tại, có thể sử dụng khi bạn chỉ muốn một số, bạn không quan tâm nhiều đến chất lượng ngẫu nhiên hoặc có mối quan tâm về bảo mật, v.v .:

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

4

Vim không cung cấp trình tạo ngẫu nhiên riêng, tuy nhiên nếu bạn đã biên dịch vim bằng Python, phương thức sau sẽ nối một chữ số ngẫu nhiên ở cuối dòng của bạn:

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

Lưu ý: Để kiểm tra xem vim của bạn có hỗ trợ Python hay không, hãy thử: :echo has('python')(1 cho có).

Bạn cũng có thể sử dụng shell cung cấp $RANDOMbiến (hoạt động với bash / ksh / zsh) để trả về một giả ngẫu nhiên (0-32767), ví dụ:

:r! echo $RANDOM

hoặc là:

:put =system('echo $RANDOM')

hoặc là:

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

Trên Windows, bạn đã cài đặt Cygwin / MSYS / SUA hoặc sử dụng %RANDOM%biến như Carpetsmoker đề xuất.

Nếu bạn không có quyền truy cập vào shell và Python, như đối với cách giải quyết, bạn sử dụng một vài chữ số cuối cùng từ dấu thời gian hiện tại, ví dụ:

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

Lưu ý: Nếu bạn đang sử dụng nó khá thường xuyên, hãy viết một chức năng đơn giản return reltimestr(reltime())[-4:].

Lưu ý: Các phương thức trên chỉ trả về một số nguyên giả ngẫu nhiên không nên được sử dụng để tạo khóa mã hóa.


Để thêm nhiều số ngẫu nhiên, vui lòng nhấn @:để lặp lại lệnh một lần nữa. Hoặc tiền tố với số (như 10@:) để thêm nhiều số ngẫu nhiên được phân tách bằng các dòng mới.


Liên quan:


Nó cũng làm việc với zsh, nhưng không phải với sh, dash, fish, csh, hoặc tcsh... Bạn có thể sử dụng :r! bash -c 'echo $RANDOM'...
Martin Tournoij

"Trả về một vài chữ số cuối cùng từ dấu thời gian hiện tại" -> Đây không phải là ngẫu nhiên. Sử dụng thời gian để có được một số giả ngẫu nhiên hầu như luôn là một ý tưởng tồi, ngay cả đối với các mục đích không phải là tiền điện tử. Điều gì xảy ra nếu độ phân giải của dấu thời gian tính bằng giây và bạn tạo một "tệp. $ Random" hai lần trong một giây? Rất tiếc! ... Thêm vào đó, bạn không bao giờ biết khi nào ai đó sẽ sử dụng của bạn GetRandom()chức năng nơi PRNG tốt không vấn đề, vì vậy nó tốt hơn để chỉ nhận được nó ngay từ đầu nếu có thể (và đó là gần như lúc nào cũng có ở đây!)
Martin Tournoij

Tôi không biết chất lượng của $RANDOMnó là gì, nhưng nếu đây là PRNG kém thì đó không phải là lý do để sử dụng PRNG thậm chí còn kém hơn :-) Thay vào đó, hãy nâng cấp lên PRNG tốt hơn! Theo như tôi biết, /dev/urandomcó sẵn trên tất cả các nền tảng bashthường có sẵn, vì vậy tôi không thấy lý do để không sử dụng nó.
Martin Tournoij 16/2/2015

1
Tôi không biết về $RANDOM. Có vẻ như là một công cụ nhỏ rất đẹp và mặc dù nó có thể là "người đàn ông nghèo RNG" (như @Carpetsmoker chỉ ra), nó chắc chắn phù hợp với yêu cầu "dễ nhớ" của @ kenorb.
Dalker

3

Tôi không nghĩ có một hàm riêng cho các số ngẫu nhiên trong Vimscript.

Một cách sử dụng :python(sử dụng nó trong một chức năng, có lẽ, với 10000 và 60 được thay thế bởi các tham số):

: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

Xem câu trả lời của tôi để Tạo một hộp trong vim qua python để có phần giới thiệu nhanh về kịch bản Python trong Vim.

vim.current.bufferlà một danh sách các chuỗi, chúng ta có thể gán một danh sách các chuỗi theo cách chúng ta làm trong Python. random.samplechỉ là cách đơn giản nhất mà tôi có thể nghĩ ra để có được danh sách các số nguyên ngẫu nhiên trong Python.


@Carpetsmoker random.samplechỉ lặp lại hai đối số trên Python 2, strlà hàm dựng sẵn để chuyển đổi mọi thứ thành chuỗi. Hãy để tôi tìm kiếm tương đương Py3 ( strsẽ giống nhau, sẽ phải kiểm tra xrangerandom.sample).
muru 14/2/2015

@Carpetsmoker aargh, lỗi đánh máy. Dấu ngoặc sau 60 được cho là sau 10000. Và xrangekhông có trong Python3 vì rangetương đương (không thực sự xây dựng một danh sách, không giống như rangetrong Py2).
muru 14/2/2015

@Carpetsmoker Và sự khác biệt cuối cùng là maptrong Py3 trả về một lần lặp và không phải là một danh sách, vì vậy dòng cuối cùng sẽ sử dụnglist(map(str, random.sample(range(10000), 60)))
muru 14/2/2015

Được rồi, tôi đã tự do chỉnh sửa bài đăng của mình với một số thay đổi (nhỏ) để làm cho nó tương thích với cả Python 2 và 3 ...
Martin Tournoij

3

Bạn có thể sử dụng các hàm rand()srand(), với điều kiện nhị phân Vim của bạn bao gồm bản vá 8.1.2342 .


Ví dụ: để tạo 10 số ngẫu nhiên được phân tách bằng dòng mới:

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

Để tạo 10 số ngẫu nhiên, tất cả đều thấp hơn 100:

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

Để tạo 10 chuỗi chữ cái ngẫu nhiên gồm 5 ký tự:

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

Để tạo 10 từ ngẫu nhiên (lấy từ tệp từ điển /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")

Để tạo 10 chuỗi gồm 5 từ ngẫu nhiên:

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

Để tạo UUID phiên bản 4 ngẫu nhiên:

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

Để áp dụng một bảng màu ngẫu nhiên:

let seed = srand()
let colorschemes = getcompletion('', 'color')
let len = colorschemes->len()
exe 'colo '..colorschemes[rand(seed) % len]
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.