summaryrefslogtreecommitdiff
path: root/distribute.lua
blob: 8c0b76c1f9b0b3565720075376c7ed52cb2bf72d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
-- 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