将一个偶数分成N份,每份都是2的倍数
Dividing an even number into N parts each part being a multiple of 2
假设我有数字 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]
简化问题:忘记 2 的倍数
首先,让我们先简化一下您的问题。忘掉 2 的倍数吧。假设你想将一个非偶数 n
分成 k
个非偶数部分。
显然,最平衡的解决方案是让某些部分为 n // k
,而某些部分为 n // k + 1
。
其中有多少?我们称 r
为 n // k + 1
的零件数。然后有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 (by) 尽可能多的次数给定余数, 然后重复 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)
这个解决方案不是很清楚也很容易理解,但它不需要任何循环。
完整代码:
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
除法的余数,将其除以 2 以补偿乘法
- last:较高的数字只是较高值的计算数量的
lower + 2
倍,较低的数字正在填充其他空间
假设我有数字 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]
简化问题:忘记 2 的倍数
首先,让我们先简化一下您的问题。忘掉 2 的倍数吧。假设你想将一个非偶数 n
分成 k
个非偶数部分。
显然,最平衡的解决方案是让某些部分为 n // k
,而某些部分为 n // k + 1
。
其中有多少?我们称 r
为 n // k + 1
的零件数。然后有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 (by) 尽可能多的次数给定余数, 然后重复 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)
这个解决方案不是很清楚也很容易理解,但它不需要任何循环。
完整代码:
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
除法的余数,将其除以 2 以补偿乘法 - last:较高的数字只是较高值的计算数量的
lower + 2
倍,较低的数字正在填充其他空间