|
| 1 | +-- Weighted/Biased random distribution implementation |
| 2 | +-- See : http://codetheory.in/weighted-biased-random-number-generation-with-javascript-based-on-probability/ |
| 3 | + |
| 4 | +-- Note: The sum of weights should be 1. That is, all |
| 5 | +-- weights are decimal values lower than 1. |
| 6 | + |
| 7 | +-- Note: As all the implementations given below uses |
| 8 | +-- math.random, one can call math.randomseed with a |
| 9 | +-- custom seed before using them. |
| 10 | + |
| 11 | +-- items : an array-list of values |
| 12 | +-- weights : a map table holding the weight for each value in |
| 13 | +-- in the `items` list. |
| 14 | +-- returns : an iterator function |
| 15 | +local function expanding_random(items, weights) |
| 16 | + local list = {} |
| 17 | + for _, item in ipairs(items) do |
| 18 | + local n = weights[item] * 100 |
| 19 | + for i = 1, n do table.insert(list, item) end |
| 20 | + end |
| 21 | + return function() |
| 22 | + return list[math.random(1, #list)] |
| 23 | + end |
| 24 | +end |
| 25 | + |
| 26 | +-- items : an array-list of values |
| 27 | +-- weights : a map table holding the weight for each value in |
| 28 | +-- in the `items` list. |
| 29 | +-- returns : an iterator function |
| 30 | +local function in_place_random(items, weights) |
| 31 | + local partial_sums, partial_sum = {}, 0 |
| 32 | + for _, item in ipairs(items) do |
| 33 | + partial_sum = partial_sum + weights[item] |
| 34 | + table.insert(partial_sums, partial_sum) |
| 35 | + end |
| 36 | + return function() |
| 37 | + local n, s = math.random(), 0 |
| 38 | + for i, si in ipairs(partial_sums) do |
| 39 | + s = s + si |
| 40 | + if si > n then return items[i] end |
| 41 | + end |
| 42 | + end |
| 43 | +end |
| 44 | + |
| 45 | +return { |
| 46 | + expanding = expanding_random, |
| 47 | + in_place = in_place_random |
| 48 | +} |
0 commit comments