【问题标题】:Dividing an even number into N parts each part being a multiple of 2将一个偶数除以 N 个部分,每个部分都是 2 的倍数
【发布时间】:2022-01-20 08:01:03
【问题描述】:

假设我有一个数字100,我需要将它分成 N 个部分,每个部分最初不应超过 30。因此,初始分组将是 (30,30,30)。余数(即 10)将通过在每个组中连续添加 2 来分配到这三个组中,从而确保每个组是 2 的倍数。因此,所需的输出应该类似于 (34,34,32)。

注意:原来的数总是偶数。

我尝试在 Python 中解决这个问题,这就是我想出的。显然,它并没有像我想象的那样工作。它通过向每个组迭代地添加 1(而不是 2,根据需要)来分配剩余部分。

num = 100
parts = num//30  #Number of parts into which 'num' is to be divided

def split(a, b):
  result = ([a//b + 1] * (a%b) + [a//b] * (b - a%b))
  return(result)

print(split(num, parts))

输出:

[34, 33, 33]

期望的输出:

[34, 34, 32]

【问题讨论】:

  • “最初不应超过 30” 为什么?为什么他们不应该超过30? “最初”有什么特别之处?你不只关心最终结果吗?
  • 我正在尝试实现这个算法来绘制一些数据。我需要确保沿轴的条目数不超过 60。在最坏的情况下,如果数字为 59,此算法将确保沿轴只有 59 个条目。

标签: python algorithm math numbers


【解决方案1】:

简化问题:忘记 2 的倍数

首先,让我们先简化一下您的问题。忘掉 2 的倍数吧。假设您想将非偶数 n 拆分为 k 非偶数部分。

显然,最平衡的解决方案是将一些部分设为n // k,而将一些部分设为n // k + 1

其中有多少?让我们用n // k + 1 将零件数称为r。然后有k - r部分和n // k,所有部分加起来为:

   (n // k) * (k - r) + (n // k + 1) * r
== (n // k) * (k - r) + (n // k) * r + r
== (n // k) * (k - r + r) + r
== (n // k) * k + r

但是部分总和应该是n,所以我们需要找到r这样:

n == (n // k) * k + r

很高兴,您可能会在这里认出欧几里得除法,n // k 是商,r 是余数。

这给了我们split函数:

def split(n, k):
    d,r = divmod(n, k)
    return [d+1]*r + [d]*(k-r)

测试:

print( split(50, 3) )
# [17, 17, 16]

分成2的倍数

现在回到您的split_even 问题。现在我们有了泛型函数split,解决split_even的简单方法是使用split

def split_even(n, k):
    return [2 * x for x in split(n // 2, k)]

测试:

print( split_even(100, 3) )
# [34, 34, 32]

泛化:m 的倍数

用除 2 以外的数字 m 的倍数做同样的事情是微不足道的:

def split_multiples(n, k, m=2):
    return [m * x for x in split(n // m, k)]

测试:

print( split_multiples(102, 4, 3) )
# [27, 27, 24, 24]

【讨论】:

  • 优雅的解释!感谢您的帮助
  • 我的想法完全正确:)
【解决方案2】:

这个解决方案不是很清楚也不太容易理解,但它不需要任何循环。

完整代码:

def split(a,b):
     lower = (a//b//2) * 2
     num = a % (b*2) // 2
     return [lower + 2] * num + [lower] * (b - num)

解释:

  • 首先获取所有部分的值:我们将除法的结果 (value // parts) 向下舍入到下一个偶数 ((x // 2) * 2)
  • 要获得较高值的数量:我们将a 除法的余数分成两倍,然后除以二来补偿乘法
  • 最后:较大的数字只是 lower + 2 乘以较高值的计算数量,而较小的数字将填充其他空格

【讨论】:

    【解决方案3】:

    我在这里的方法是创建三个数组并将它们相加,前两个很简单,但最后一个更复杂一些 - 它只是重复 2 (乘以)尽可能多的余数,然后代表0s。

    # Part 1
    np.repeat(first, x//first) 
    # Part 2
    np.repeat(by, x//first)
    # Part 3
    np.repeat([by, 0], [(x//first) - ((x - (x//first*first)) // by % by), (x - (x//first*first)) // by % by])
    

    包装成一个函数:

    def split(x, first, by):
      return(np.repeat(first, x//first) + np.repeat(by, x//first) + np.repeat([by, 0], [(x//first) - ((x - (x//first*first)) // by % by), (x - (x//first*first)) // by % by]))
    
    split(100, 30, 2)
    

    【讨论】:

    • 为了便于使用和理解,能否请您将此方法封装成一个函数,并带有要拆分的数量和部分数量的参数?而不是硬编码 100 和 30。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-01-07
    相关资源
    最近更新 更多