Ruby 如何获取一个整数并根据百分比将其划分为整数?
就算法而言,我有点头疼。我正在使用ruby,但这可能是一个普通的编程问题。以下是业务需求: 假设我们有5名销售代表,每个人都有一定比例的积压工作(要完成的工作)。假设积压工作价值50万美元。每个销售代表都有一定的百分比。下面是一个任意的例子:Ruby 如何获取一个整数并根据百分比将其划分为整数?,ruby,algorithm,math,Ruby,Algorithm,Math,就算法而言,我有点头疼。我正在使用ruby,但这可能是一个普通的编程问题。以下是业务需求: 假设我们有5名销售代表,每个人都有一定比例的积压工作(要完成的工作)。假设积压工作价值50万美元。每个销售代表都有一定的百分比。下面是一个任意的例子: 销售代表A:$53230(预算的10.646%) 销售代表B:$102202(预算的20.4404%) 销售代表C:$72694(占预算的14.5388%) 销售代表D:$129230(占预算的25.846%) 销售代表E:$142644(占预算的28.
- 销售代表A:$53230(预算的10.646%)
- 销售代表B:$102202(预算的20.4404%)
- 销售代表C:$72694(占预算的14.5388%)
- 销售代表D:$129230(占预算的25.846%)
- 销售代表E:$142644(占预算的28.5292%)
我如何确保他们根据百分比平均分配,但确保只使用/全部使用50名员工?(如果我只是对数字进行四舍五入,您可能会得到51或49)?始终使用较低的结果,在本例中为49,然后有第二个例程优先考虑剩余部分的分配方式,例如,按最高百分比或最佳销售人员等。将该列表称为剩余部分分配列表 现在,由于余数总是小于除数,从余数分布列表的顶部项目开始,分配一个到列表的顶部,然后分配一个到列表的下一个,等等。当您没有单位时,您就完成了。在你的情况下,你只有一个单位分配,所以你只分配一个 我在从仓库分发包裹时遇到了类似的问题。与模运算配合得很好。“…确保它们均匀分配…”含糊不清。如果将其视为一个优化问题,我们需要最小化偏差的数值度量。例如,如果其中一名销售代表分配了
15名
员工,但根据销售额百分比,其应得14.3
,则偏差可被视为(15-14.3)。abs#=>0.7
。如果我们希望最小化所有销售代表的最大偏差,则可以使用整数规划获得最佳解决方案
显然需要更简单的东西。我倾向于按销售顺序将员工分配给代表,从最低到最高,根据销售百分比四舍五入浮动
代码
def allocate_workers(sales, workers)
tot_sales = sales.values.sum.to_f
sales.sort_by(&:last).each_with_object({}) do |(rep, amt),h|
h[rep] = (workers * amt/tot_sales).round
tot_sales -= amt
workers -= h[rep]
end
end
sales = { A: 53_230, B: 102_202, C: 72_694, D: 129_230, E: 142_644 }
workers = 50
allocate_workers(sales, workers)
#=> {:A=>5, :C=>7, :B=>10, :D=>13, :E=>15}
示例
def allocate_workers(sales, workers)
tot_sales = sales.values.sum.to_f
sales.sort_by(&:last).each_with_object({}) do |(rep, amt),h|
h[rep] = (workers * amt/tot_sales).round
tot_sales -= amt
workers -= h[rep]
end
end
sales = { A: 53_230, B: 102_202, C: 72_694, D: 129_230, E: 142_644 }
workers = 50
allocate_workers(sales, workers)
#=> {:A=>5, :C=>7, :B=>10, :D=>13, :E=>15}
解释
对于上述示例,步骤如下所示
a = sales.values
#=> [53230, 102202, 72694, 129230, 142644]
b = a.sum
#=> 500000
tot_sales = b.to_f
#=> 500000.0
c = sales.sort_by(&:last)
#=> [[:A, 53230], [:C, 72694], [:B, 102202], [:D, 129230], [:E, 142644]]
e = c.each_with_object({})
#=> #<Enumerator: [[:A, 53230], [:C, 72694], [:B, 102202], [:D, 129230],
# [:E, 142644]]:each_with_object({})>
因此,销售代表:分配了5名员工(从5.323
四舍五入),剩下45名员工分配给剩余的4名销售代表,他们的总销售额为500000.0-53230#=>446770.0
生成枚举器e
的下一个元素并将其传递给块,从而使块变量具有以下值
(rep, amt),h = e.next
#=> [[:C, 72694], {:A=>5}]
rep
#=> :C
amt
#=> 72694
h
#=> {:A=>5}
请注意,h
(将返回)已更新。其余的计算遵循传递给块的e
中第一个元素的计算
处理销售额最大的销售代表(:E
)时,块变量将
rep
#=> :E
amt
#=> 142644
h
#=> {:A=>5, :C=>7, :B=>10, :D=>13}
我们会有
tot_sales
#=> 142644.0 (approx.)
workers
#=> 15
因此,rep:E
将获得所有
15 * 142644/142644.0).round
#=> 15
剩余工人。轮⇒ 做数学⇒ <代码>[49,51]。有吗?&&将_或_减去_至_min _或_max
。没有办法让一些员工“剩下”(考虑一下这样的情况,当你有两名销售代表,A 50%和B 50%,以及三名员工时:你不能将这三名员工分成两名)。你只需决定如何处理剩余的员工:将他们随机分配给一名代表,或者分配给拥有最少的一名代表,或者是最多的,或者别的什么。谢谢大家。回想起来,这很简单!