Search code examples
listrandomkdbq-langnul

KDB / Q Resetting random elements on newly created list (numerical vs symbol/char)


I am having a random (Y) list with (X) elements (seed elements in 2nd dimension) where I want to reset values on a random factor (Z) that is between 0f and 1f. For numerical lists this code works fine

q)seed:20
q){(0>z-(x#seed)?\:1f)*(x#seed)?\:y}[3;10;0.25]

How can I extend that code to be running also in the case of symbols (or char lists) like that

q){(0>z-(x#seed)?\:1f)*(x#seed)?\:y}[3;`8;0.25]
q){(0>z-(x#seed)?\:1f)*(x#seed)?\:y}[3;" ";0.25]

I guess the multiplication in the middle is the problem, but I dont know how to make it more generic.

Maybe there is even a more elegant solution to this problem than creating 2 lists and handling it like that.

Thanks


Solution

  • To make it generic would be a matter of using the booleans to index rather than using them to multiply (as you currently are). However, for non numerical lists you'd need to reset values to nulls rather than to zero. These nulls would have to be the correct null corresponding to the type of the input (i.e. 0Ni for ints, 0Nj for longs, ` for symbols, " " for chars etc) - this can be achieved with 'first 0#'

    So the generic version of your function would be something like:

    q){seed cut @[(x*seed)?y;where 0<=z-(x*seed)?1f;:;first 0#y]}[3;10;0.25]
      9 3 9 4 9     9   8 7 6 1   3 4 9 3 9
    2 6 5 3 5 6 0 8 9 0   8 9   1 5 7 4 3 2
    3 7 6 9 8 2 2 8 9   8 2       5 1 2 1 3
    
    q){seed cut @[(x*seed)?y;where 0<=z-(x*seed)?1f;:;first 0#y]}[3;`8;0.25]
    eklinmcm ikfknpam          pjncfmob mmhpkfap                   bhakgffh khkag..
             neohaicn fiajkigo          bllnecdn          hpnommjb pkhpildh lacif..
             feinbhmg mbpkjapc                   dgippbmi lelmkfoe               ..
    
    q){seed cut @[(x*seed)?y;where 0<=z-(x*seed)?1f;:;first 0#y]}[3;" ";0.25]
    "rk an i nts d cxfkp "
    "oiusc udpliqbqnzapql"
    "qhk yauhroflprr lwuw"
    

    Having said that, this may not be the best way to approach the initial problem - this is only a suggestion for making it generic.

    PS. If you still want zeros in the numerical lists then use zero-fill

    q)0^{seed cut @[(x*seed)?y;where 0<=z-(x*seed)?1f;:;first 0#y]}[3;10;0.25]
    7 0 5 1 1 0 3 2 0 0 0 0 0 3 0 9 7 9 7 7
    6 9 4 0 4 4 0 6 2 9 5 1 0 0 8 9 6 3 4 0
    5 0 8 1 1 6 4 9 0 1 9 5 8 9 0 3 9 0 0 1