Python 如何分配整数列表以尽可能接近平衡?

Python 如何分配整数列表以尽可能接近平衡?,python,algorithm,Python,Algorithm,如何平衡一组项目?通过平衡,4个变量中的每一个与任何其他变量的方差不应超过+1 每个数字必须保持完整,因为它们代表要传输的1个物理项 输入a=1、b=2、c=3、d=10 输出a=4,b=4,c=4,d=4 输出: 将3从d移到a 将2从d移到b 将1从d移到c 输入a=1,b=2,c=0,d=0 输出a=1,b=1,c=1,d=0 输出: 将1从b移到c 输入a=1,b=0,c=0,d=0 输出a=1,b=0,c=0,d=0 输出: 不动 输入a=0,b=1,c=0,d=1 输出a=0,b=1

如何平衡一组项目?通过平衡,4个变量中的每一个与任何其他变量的方差不应超过+1

每个数字必须保持完整,因为它们代表要传输的1个物理项

输入a=1、b=2、c=3、d=10
输出a=4,b=4,c=4,d=4
输出:
将3从d移到a
将2从d移到b
将1从d移到c
输入a=1,b=2,c=0,d=0
输出a=1,b=1,c=1,d=0
输出:
将1从b移到c
输入a=1,b=0,c=0,d=0
输出a=1,b=0,c=0,d=0
输出:
不动
输入a=0,b=1,c=0,d=1
输出a=0,b=1,c=0,d=1
输出:
不动
这是一个开始

要获得平衡值,可以将平均值分配给每个变量。还有一些剩余(求和模len),只需将其分配到第一个变量:

def distribute(*values):
    low = min(values)
    high = max(values)
    if high - low <= 1:
        print 'already balanced'
        return list(values)
    s = sum(values)
    n = len(values)
    avg = s // n
    result = [avg] * n
    for i in range(s % n):
        result[i] += 1
    return result

print(distribute(1, 2, 0, 0))
# [1, 1, 1, 0]
def分布(*值):
低=最小值(数值)
高=最大值(数值)
如果高-低这是一个开始

要获得平衡值,可以将平均值分配给每个变量。还有一些剩余(求和模len),只需将其分配到第一个变量:

def distribute(*values):
    low = min(values)
    high = max(values)
    if high - low <= 1:
        print 'already balanced'
        return list(values)
    s = sum(values)
    n = len(values)
    avg = s // n
    result = [avg] * n
    for i in range(s % n):
        result[i] += 1
    return result

print(distribute(1, 2, 0, 0))
# [1, 1, 1, 0]
def分布(*值):
低=最小值(数值)
高=最大值(数值)

如果high-lowNo,则它不是一组if/else语句。将值放入列表中,而不是单独的变量。取平均值,截断为整数。在另一个相同长度的列表中复制该意思。你现在有了

vals = [1, 3, 4, 10]
mean = [4, 4, 4, 4]
请注意,您还剩下2项。你需要分发这些。 在“平均值”列表中,向超出平均值的任何元素添加1,直到用完剩余或元素。你现在有

vals = [1, 3, 4, 10]
mean = [4, 4, 4, 5]
在这种情况下,您还剩下1个。将其添加到任何其他元素:

vals = [1, 3, 4, 10]
mean = [4, 5, 4, 5]
现在,一次比较一个元素的列表,并报告所需的移动,这是一个三部曲。这将为您提供移动项目的最小数量,以获得所需的分布

这能让你走吗


对OP评论的回应

首先,你的帖子要求的是余额,而不是所需的一系列转账。下一步,我不认为这不是小事。小于“mean”数组的任何内容都是收件人;更多的都是捐赠者。你永远不会让产品移动超过一次:只需将转移限制在可用数量和所需数量中较小的一个

考虑一个简单但不平凡的案例:

vals = [1, 2, 10, 1, 6]
mean = [4, 4, 4, 4, 4]
diff = [-3, -2, 6, -3, 2]
您可以按任何顺序识别移动;为了简单起见,我们将在两组中从右向左。是的,有一个简单的解决方案,如果E给B多出2个,而C给A和D各提供3个,但问题不需要最少的发货量,只需要有效的移动项目数量

A有1个项目,但需要4个:从C中取出,第一个元素有一个多余部分,它有6个多余部分

vals = [4, 2, 7, 1, 6]
mean = [4, 4, 4, 4, 4]
diff = [0 -2, 3, -3, 2]
B还需要2个项目,也可以从C获得:

vals = [4, 4, 5, 1, 6]
mean = [4, 4, 4, 4, 4]
diff = [0, 0, 1, -3, 2]
D还需要3个,但C只剩下一个:拿着它

vals = [4, 4, 4, 2, 6]
mean = [4, 4, 4, 4, 4]
diff = [0, 0, 0, -2, 2]
。。。最后,最后一次转移是显而易见的


这会让你再次行动吗?

不,这不是一组if/else语句。将值放入列表中,而不是单独的变量。取平均值,截断为整数。在另一个相同长度的列表中复制该意思。你现在有了

vals = [1, 3, 4, 10]
mean = [4, 4, 4, 4]
请注意,您还剩下2项。你需要分发这些。 在“平均值”列表中,向超出平均值的任何元素添加1,直到用完剩余或元素。你现在有

vals = [1, 3, 4, 10]
mean = [4, 4, 4, 5]
在这种情况下,您还剩下1个。将其添加到任何其他元素:

vals = [1, 3, 4, 10]
mean = [4, 5, 4, 5]
现在,一次比较一个元素的列表,并报告所需的移动,这是一个三部曲。这将为您提供移动项目的最小数量,以获得所需的分布

这能让你走吗


对OP评论的回应

首先,你的帖子要求的是余额,而不是所需的一系列转账。下一步,我不认为这不是小事。小于“mean”数组的任何内容都是收件人;更多的都是捐赠者。你永远不会让产品移动超过一次:只需将转移限制在可用数量和所需数量中较小的一个

考虑一个简单但不平凡的案例:

vals = [1, 2, 10, 1, 6]
mean = [4, 4, 4, 4, 4]
diff = [-3, -2, 6, -3, 2]
您可以按任何顺序识别移动;为了简单起见,我们将在两组中从右向左。是的,有一个简单的解决方案,如果E给B多出2个,而C给A和D各提供3个,但问题不需要最少的发货量,只需要有效的移动项目数量

A有1个项目,但需要4个:从C中取出,第一个元素有一个多余部分,它有6个多余部分

vals = [4, 2, 7, 1, 6]
mean = [4, 4, 4, 4, 4]
diff = [0 -2, 3, -3, 2]
B还需要2个项目,也可以从C获得:

vals = [4, 4, 5, 1, 6]
mean = [4, 4, 4, 4, 4]
diff = [0, 0, 1, -3, 2]
D还需要3个,但C只剩下一个:拿着它

vals = [4, 4, 4, 2, 6]
mean = [4, 4, 4, 4, 4]
diff = [0, 0, 0, -2, 2]
。。。最后,最后一次转移是显而易见的


这会让你再次行动吗?

你没有正确地指定“平衡”的含义。在这种情况下,术语集有点混乱。Python
set
类型及其所基于的数学集本质上是无序的。@KennyPowers采用平均值显然是明智的,您只需处理平均值不是整数的情况,这并不特别困难。我建议你自己再考虑一下。对于社区来说,我在这里得不到支持票。我已经回答了这个问题所有可能模糊的部分。我不是在问这个问题的答案。只是一些指针,这样我就可以学习了。所以总的来说,我养成了这样一种习惯,即在有人不高兴的问题上飞过,投了反对票,然后走开。@KennyPowers:我想投反对票是因为你的问题没有表现出任何解决问题的特别尝试。评论中有一些工作,但您尚未正确更新帖子。你需要这样做,这是很容易交流