-- min, weight, receive local function eliminate(budget, total_weight, elems) if budget < 0 then return end if total_weight == 0 then return 0 end local unit = budget / total_weight for i, e in ipairs(elems) do local allocated = unit * e.weight if e.min > allocated then e.receive = e.min table.remove(elems, i) budget = budget - e.min total_weight = total_weight - e.weight return eliminate(budget, total_weight, elems) end end return unit end local function distribute(budget, elems) local total_weight = 0 local remaining = {} for _, v in pairs(elems) do total_weight = total_weight + v.weight table.insert(remaining, v) end local unit = eliminate(budget, total_weight, remaining) if not unit then for _, e in ipairs(remaining) do e.receive = e.min end return false end for _, e in ipairs(remaining) do e.receive = unit * e.weight end return true end return distribute