Search code examples
j

Using less trivial random generation in J lang


I am experimenting with random generation using J and would have a couple of questions that occured:

  1. If I want to pick random 10-character word I can use
   (?10 # 26) { 'abcdefghijklmnopqrstuvwxyz'
vqdffhrvso

What would be the best way to pick N of them? For example, three 10-character words?

  1. Going deeper with the example 1. How about non-repeating picking? The above-mentioned is picking with repetition.

  2. I can choose 4 digit number like below

(?5 # 10) { '0123456789'
40400

(a) How to sneak a condition that 0 cannot be the first digit? (b) How to say for example I want to pick natural number from <1234,1250> UNION (9999, 10002> ? (c) How to pick real number in the same set?

  1. Extending point 3. How to pick randomly from 1, 3, 6, 10 knowing that the probability weights are 0.1, 0.3, 0.5, 0.1, respectively?

  2. How to pick number for any distribution?

Thanks in advance for the feedback!


Solution

  • What would be the best way to pick N of them?

    Here are two ways:

       ]alfa =: a. {~ (a.i.'a')+i.26
    abcdefghijklmnopqrstuvwxyz
       rand =: alfa {~ ] ?@$ #@alfa
       rand 10
    kuipaajyvm
       rand 3 10  NB. generate a 2d array of indices into alfa (rand called 1x)
    zlqtjfcurj
    odzdfcuqiy
    mjmrylxpau
       rand&10"0 i.3  NB. generate three lists of indices (rand called 3x)
    akfklfxuit
    scqehljoah
    pcptwgqdmm
    

    How about non-repeating picking?

    Dyadic ? offers non-repetition. What you're using above is monadic ? against a list of arguments.

       sel =: alfa {~ (#alfa) ?~ ]
       sel&10"0 i.5
    ysxagmekid
    wbdqzkanum
    wynmjuvcti
    arhwqpegou
    ofjigrctdn
       sel 30   NB. impossible
    |domain error: sel
    |       sel 30
    

    How to sneak a condition that 0 cannot be the first digit?

    1. generate the first digit separately from the rest of the digits
    2. keep generating answers until one satisfies the condition
       NB. option 1
       number =: 10 #. (>:@? bind 9) , (10 ?@$~ <:)
       number 3
    212
       +/ 99 < (number bind 3)"0 i.1e4
    10000
    
       NB. option 2
       number =: 10 #. 10 ?@$~ ]
       number 3
    831
       +/ 99 < (number bind 3)"0 i.1e4  NB. some results with leading 0
    8988
    
       NB. fold single, an infinite loop with a break
       goodnumber =: {{ (10^y-1)&{{y[1 Z: x <: y}} F. (number bind y) '' }}
       goodnumber 3
    912
       +/99 < (goodnumber bind 3)"0 i.1e4  NB. no bad results
    10000
    

    probability weights

    https://code.jsoftware.com/wiki/Fifty_Shades_of_J/Chapter_14

    pick a number for any distribution

    look at load 'stats/base/random'