A colleague described a simple problem to me: If there are three values A, B, and C, and the probabilities of selecting each value are 27%, 8%, and 65% respectively, then how do I write a function that randomly selects a value according to its chances?
I thought this would be a good chance to practice some J again, so I worked it out as follows.
vals =. 'a';'b';'c'
┌─┬─┬─┐
│a│b│c│
└─┴─┴─┘
weights =. 27 8 65
27 8 65
max =. +/weights
100
r =. ?max
34
steps =. +/\weights
27 35 100
mask =. r < steps
0 1 1
mask # vals
┌─┬─┐
│b│c│
└─┴─┘
{. mask # vals
┌─┐
│b│
└─┘
And the obligatory point-free definition.
pick =: {.@#~((?@+/)<+/\)
I get C most times, which suggests the weights are working.
vals pick weights
┌─┐
│c│
└─┘
With J having so many statistical applications, I imagine this problem has been resolved in a more elegant manner elsewhere, but it was fun writing some again.