summaryrefslogtreecommitdiff
path: root/distribute.lua
diff options
context:
space:
mode:
Diffstat (limited to 'distribute.lua')
-rw-r--r--distribute.lua48
1 files changed, 48 insertions, 0 deletions
diff --git a/distribute.lua b/distribute.lua
new file mode 100644
index 0000000..8c0b76c
--- /dev/null
+++ b/distribute.lua
@@ -0,0 +1,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