Skip to content

Instantly share code, notes, and snippets.

@klesse413
Created Jul 27, 2017
Embed
What would you like to do?
module Allocator
module_function
def allocate(inflow, weightings)
raise 'Inflow and weightings must be present' unless [inflow, weightings].all?(&:present?)
raise 'Inflow and weightings must be Integers' unless (weightings + [inflow]).all? { |input| input.is_a?(Integer) }
allocations, remainders = apportion_with_remainder(inflow, weightings).transpose
remaining_inflow = inflow - allocations.sum
deserving_indices = remainders.each_with_index.sort_by { |remainder, i| [remainder, i] }.reverse.map { |_remainder, i| i }.first(remaining_inflow)
allocations.each_with_index.map do |allocation, i|
deserving_indices.include?(i) ? allocation + 1 : allocation
end
end
def apportion_with_remainder(input, buckets)
total = buckets.sum
buckets.map do |bucket|
(input * bucket).divmod(total)
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment