为了账号安全,请及时绑定邮箱和手机立即绑定

通过一组槽尽可能均匀地分配整数数量

通过一组槽尽可能均匀地分配整数数量

HUWWW 2021-10-19 17:16:41
我试图找到一种优雅的方式来实现将金额分配到 Python 中给定的一组插槽中。例如:分布在 4 个盘子上的 7 个橙子将返回:[2, 2, 2, 1]4 个盘子上的 10 个橙子将是:[3, 3, 2, 2]
查看完整描述

3 回答

?
九州编程

TA贡献1785条经验 获得超4个赞

从概念上讲,您要做的是计算7 // 4 = 1和7 % 4 = 3。这意味着所有的盘子都会变成 1 个完整的橙色。剩下的 3 个告诉你,其中三个盘子得到了一个额外的橙色。


该divmod内置是同时获得这两个量的快捷方式:


def distribute(oranges, plates):

    base, extra = divmod(oranges, plates)

    return [base + (i < extra) for i in range(plates)]

以你的例子:


>>> distribute(oranges=7, plates=4)

[2, 2, 2, 1]

为了完整起见,您可能想要检查它oranges是非负数plates还是正数。鉴于这些条件,这里有一些额外的测试用例:


>>> distribute(oranges=7, plates=1)

[7]


>>> distribute(oranges=0, plates=4)

[0, 0, 0, 0]


>>> distribute(oranges=20, plates=2)

[10, 10]


>>> distribute(oranges=19, plates=4)

[5, 5, 5, 4]


>>> distribute(oranges=10, plates=4)

[3, 3, 2, 2]


查看完整回答
反对 回复 2021-10-19
?
慕妹3242003

TA贡献1824条经验 获得超6个赞

疯狂物理学家的答案是完美的。但是,如果你要分发uniformley上板橘子(如2 3 2 3VS2 2 3 3在7个橙子和4个板为例),这里是一个简单的想法。


简易案例

以 31 个橙子和 7 个盘子为例。


第 1 步:你像疯狂物理学家一样开始欧几里德除法:31 = 4*7 + 3。每个盘子里放 4 个橙子,剩下的 3 个。


[4, 4, 4, 4, 4, 4, 4]

第 2 步:现在,您的盘子比橙子多,这完全不同:您必须在橙子之间分配盘子。您还剩 7 个盘子和 3 个橙子:7 = 2*3 + 1。每个橙子将有 2 个盘子(您还剩下一个盘子,但没关系)。让我们把这种2的leap。开始leap/2会很漂亮:


[4, 5, 4, 5, 4, 5, 4]

没那么容易的案子

那是最简单的情况。34 个橙子和 7 个盘子会发生什么?


第 1 步:您仍然像 Mad Physicist 一样开始使用欧几里得除法:34 = 4*7 + 6。每个盘子里放 4 个橙子,剩下的 6 个。


[4, 4, 4, 4, 4, 4, 4]

第 2 步:现在,您还剩下 7 个盘子和 6 个橙子:7 = 1*6 + 1。每个橙子将有一个盘子。但是等等……我没有7个橙子!别怕,我借给你一个苹果:


[5, 5, 5, 5, 5, 5, 4+apple]

但是如果你想要一些统一,你必须把那个苹果放在别处!为什么不尝试在第一种情况下像橙子一样分发苹果?7个盘子,1个苹果:7 = 1*7 + 0。的leap是如图7所示,在开始leap/2,即3:


[5, 5, 5, 4+apple, 5, 5, 5]

第 3 步。你欠我一个苹果。请把我的苹果还给我:


[5, 5, 5, 4, 5, 5, 5]

总结一下:如果你只剩下几个橙子,你就分布峰,否则你分布谷。(免责声明:我是这个“算法”的作者,我希望它是正确的,但如果我错了,请纠正我!)


编码

话不多说,上代码:


def distribute(oranges, plates):

    base, extra = divmod(oranges, plates) # extra < plates

    if extra == 0:

        L = [base for _ in range(plates)]

    elif extra <= plates//2:

        leap = plates // extra

        L = [base + (i%leap == leap//2) for i in range(plates)]

    else: # plates/2 < extra < plates

        leap = plates // (plates-extra) # plates - extra is the number of apples I lent you

        L = [base + (1 - (i%leap == leap//2)) for i in range(plates)]

    return L

一些测试:


>>> distribute(oranges=28, plates=7)

[4, 4, 4, 4, 4, 4, 4]

>>> distribute(oranges=29, plates=7)

[4, 4, 4, 5, 4, 4, 4]

>>> distribute(oranges=30, plates=7)

[4, 5, 4, 4, 5, 4, 4]

>>> distribute(oranges=31, plates=7)

[4, 5, 4, 5, 4, 5, 4]

>>> distribute(oranges=32, plates=7)

[5, 4, 5, 4, 5, 4, 5]

>>> distribute(oranges=33, plates=7)

[5, 4, 5, 5, 4, 5, 5]

>>> distribute(oranges=34, plates=7)

[5, 5, 5, 4, 5, 5, 5]

>>> distribute(oranges=35, plates=7)

[5, 5, 5, 5, 5, 5, 5]


查看完整回答
反对 回复 2021-10-19
  • 3 回答
  • 0 关注
  • 192 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信