Skip to content

Instantly share code, notes, and snippets.

@trylks
Last active August 29, 2015 14:06
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save trylks/10ba4e798cad26510008 to your computer and use it in GitHub Desktop.
Save trylks/10ba4e798cad26510008 to your computer and use it in GitHub Desktop.
Programming kata suggested by a friend, formulation not available at this moment.
def allocate(amount, weights):
total = sum(weights)
for weight in weights:
assign = round(weight * amount / total) if total else 0
yield assign
amount -= assign
total -= weight
if __name__ == "__main__":
for testCase in [(10, [4,4,1]), (1, [2,4,1]), (1000, [34,4,12])]:
print(list(allocate(*testCase)))
package main
import collection.JavaConversions._
object Allocator {
def main(args: Array[String]) {
val intargs = args.map(_.toInt)
println(allocate(intargs(0), intargs.slice(1, intargs.size).toVector))
}
// Intermediate results
case class IR(val weight: Int, val assigned: Int, val originalOrder: Int, val unfairness: Double)
def allocate(amount: Int, weights: Vector[Int]): Vector[Int] = {
val proportion = amount.toDouble / weights.sum
val firstApproximation = weights
.zip(1 to weights.length)
.map { case (weight, order) => makeIR(weight, proportion, order) }
val missing = amount - firstApproximation.map(_.assigned).sum
// patch and return
firstApproximation
.sortBy(-_.unfairness)
.zip(Vector.fill(missing)(1) ++ Vector.fill(weights.length - missing)(0))
.map { case (ir, inc) => ir.copy(assigned = ir.assigned + inc) }
.sortBy(_.originalOrder)
.map(_.assigned)
}
def makeIR(weight: Int, proportion: Double, originalOrder: Int): IR = {
val thefloor = math.floor(weight * proportion).toInt
IR(weight, thefloor, originalOrder, weight * proportion - thefloor)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment