use binarySearch.frink
/** This class generates random elements from a discrete set with a
known distribution, for example, the frequency of letters in the English
language.
HOWEVER, when generating random items, it is O(log n) with a
worst case of O(n) (where n is the number of items to be chosen from).
For a better constant-time algorithm, see DiscreteDistribution.frink .
However, an O(1) efficient algorithm can be found in the
DiscreteDistribution.frink sample program.
*/
class randomDistribution
{
// An array of elements
var elements
// The sum of probabilities
var sum
new[] :=
{
elements = new array
sum = 0
}
// Adds an item with the specified probability.
add[item, prob] :=
{
sum = sum + prob
elements.push[ [item, prob, sum] ]
}
// Selects a random item based on the specified probabilities.
random[] :=
{
z = randomFloat[0, sum]
index = binarySearch[elements, z, {|a,b| a <=> b@2}]
return elements@index@0
}
}