Native Vim Random number script

夙愿已清 提交于 2019-12-20 12:42:51

问题


I know that there are various ways to get random numbers, eg, from the shell. However, I'm running vim on an android phone with very little compiled in. Also, it does not have to be rigorously random. The point is, what's an interesting, or concise, or fast (that is, with vim native functions), or short way to get a sequence of reasonably good random numbers in Vim?


回答1:


Try something like

function Rand()
    return str2nr(matchstr(reltimestr(reltime()), '\v\.@<=\d+')[1:])
endfunction

. I know no better option then using some of the time functions (there are two of them: reltime() and localtime(), but the latter is updated only each second). I would prefer to either avoid random numbers or use pyeval('random.randint(1, 10)') (preceded by python import random), because shell is slow and I don’t trust time-based solutions.

Note: documentation says that format of the item returned by reltime() depends on the system, thus I am using reltimestr(), not doing something with reltime()[1] which looks like if it contains nanoseconds.




回答2:


I've recently played around with random numbers in Vim script myself. Here are some resources that I found in the process.

No Vim script

By all means, use an external random number generator if you can. As a rule, they are better and faster than anything that could be done in Vim script.

For example, try

  • :python import random; print random.randrange(1, 7)
  • :echo system('echo $RANDOM')
  • another scripting language, for example Ruby

Libraries

Vim script libraries. These hopefully strive to provide decent quality RNG implementations.

  • vital.vim is an excellent and comprehensive library created by the vim-jp user group. Their random number generator sports an impressive array of functionality and is the best pure Vim script RNG I know of. vital.vim uses an Xorshift algorithm. Check it out!

    Rolling a die with vital.vim:

    let Random = vital#of('vital').import('Random')
    echo Random.range(1, 7)
    
  • vim-rng is a small random number generator plugin. It exports a couple of global functions that rely on a multiply-with-carry algorithm. This project seems to be a work in progress.

    Rolling a die with rng:

    echo RandomNumber(1, 6)
    
  • magnum.vim is my own little big integer library. I've recently added a random number generator that generates integers of any size. It uses the XORSHIFT-ADD algorithm.

    Rolling a die with magnum.vim:

    let six = magnum#Int(6)
    echo magnum#random#NextInt(six).Add(magnum#ONE).Number()
    
  • Rndm has been around for much longer than the other libraries. Its functionality is exposed as a couple of global functions. Rolling a die with Rndm:

    echo Urndm(1, 6)
    

Discussion and snippets

Finally, a few links to insightful discussion and Vim script snippets.

  • ZyX's reltime snippet on this page.

  • loreb's vimprng project on GitHub has an impressive number of RNG implementations in Vim script. Very useful.

  • This old mailing list discussion has a couple of Vim script snippets. The first one given by Bee-9 is limited to 16 bit but I found it quite effective. Here it is:

    let g:rnd = localtime() % 0x10000
    
    function! Random(n) abort
      let g:rnd = (g:rnd * 31421 + 6927) % 0x10000
      return g:rnd * a:n / 0x10000
    endfunction
    
  • Another script, found in a person named Bart's personal config files.

  • Episode 57 on Vimcasts.org discusses Vim's 'expression register' and refers to random number examples throughout. Refers to this Stackoverflow question and ZyX's snippet. Recommended.

  • The Vim wiki on wikia has an article 'Jump to a random line' that has a few resources not mentioned yet.




回答3:


Based on others' answers and other resources from the internet, I have written two functions to generate a random integer in the given range [Low, High].

Both the two functions receive two arguments: Low and High and return a random number in this range.

Combine Python and Vim script

The first function combines Python and Vim script.

" generate a random integer from range [Low, High] using Python
function! RandInt(Low, High) abort
" if you use Python 3, the python block should start with `python3` instead of
" `python`, see https://github.com/neovim/neovim/issues/9927
python3 << EOF
import vim
import random

# using vim.eval to import variable outside Python script to python
idx = random.randint(int(vim.eval('a:Low')), int(vim.eval('a:High')))

# using vim.command to export variable inside Python script to vim script so
# we can return its value in vim script
vim.command("let index = {}".format(idx))
EOF

return index
endfunction

Pure Vim script

The second function I propose uses pure vim script:

function! RandInt(Low, High) abort
    let l:milisec = str2nr(matchstr(reltimestr(reltime()), '\v\.\zs\d+'))
    return l:milisec % (a:High - a:Low + 1) + a:Low
endfunction

If you want to generate random number in non-serious occasions, you may use the two functions as a starter.



来源:https://stackoverflow.com/questions/12737977/native-vim-random-number-script

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!