Ruby 如何获取一个整数并根据百分比将其划分为整数?

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.

就算法而言,我有点头疼。我正在使用ruby,但这可能是一个普通的编程问题。以下是业务需求:

假设我们有5名销售代表,每个人都有一定比例的积压工作(要完成的工作)。假设积压工作价值50万美元。每个销售代表都有一定的百分比。下面是一个任意的例子:

  • 销售代表A:$53230(预算的10.646%)
  • 销售代表B:$102202(预算的20.4404%)
  • 销售代表C:$72694(占预算的14.5388%)
  • 销售代表D:$129230(占预算的25.846%)
  • 销售代表E:$142644(占预算的28.5292%)
现在让我们假设我们想要分配一定数量的可用员工,这些销售代表被分配来完成这项工作。例如,假设有50名工人可以根据这些百分比进行分配


我如何确保他们根据百分比平均分配,但确保只使用/全部使用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%,以及三名员工时:你不能将这三名员工分成两名)。你只需决定如何处理剩余的员工:将他们随机分配给一名代表,或者分配给拥有最少的一名代表,或者是最多的,或者别的什么。谢谢大家。回想起来,这很简单!