For example, S = 1000, and we want to decompose 1000 into a sum of type 17x + 20y + 150z, so that 17x + 20y + 150z is less than 1000
如果它小于1000,它就不是1000的分区。你知道吗
所以我假设您想生成从0.8S到S的所有数字的分区。你知道吗
I've come across a solution of a similar problem, but I am having trouble understanding how can I store the values into an array.
只要做list(partitions(n))。对于您的问题:
[list(partitions(i)) for i in range(int(0.8*S), S)]
其中partitions是您链接到的函数,由David Eppstein发布,我将复制到下面:
def partitions(n):
# base case of recursion: zero is the sum of the empty list
if n == 0:
yield []
return
# modify partitions of n-1 to form partitions of n
for p in partitions(n-1):
yield [1] + p
if p and (len(p) < 2 or p[1] > p[0]):
yield [p[0] + 1] + p[1:]
from itertools import count
mx, my, mz = 17, 20, 150
lo = 990
hi = 1000
solns = []
for z in count(1):
sz = z * mz
if sz > hi:
break
for y in count(1):
sy = sz + y * my
if sy > hi:
break
d = lo - sy
x = max(1, -(-d // mx))
for x in count(x):
s = sy + x * mx
if s > hi:
break
t = (z, y, x, s)
solns.append(t)
print(len(solns))
for t in solns:
print(t)
def linear_sum(lo, hi, coeff):
''' Find all positive integer solutions of the linear equation with
coefficients `coeff` with sum `s`: lo <= s <= hi
'''
num = len(coeff)
vector = [1] * num
mx = coeff[-1]
s = sum(coeff[:-1])
while True:
olds = s
xlo = max(1, -((s - lo) // mx))
xhi = 1 + (hi - s) // mx
s += mx * xlo
for vector[-1] in range(xlo, xhi):
yield s, tuple(vector)
s += mx
# Increment next vector component
k = num - 2
vector[k] += 1
s = olds + coeff[k]
# If the component is too high
while s > hi:
if not k:
return
# reset this component,
s -= coeff[k] * (vector[k] - 1)
vector[k] = 1
# and increment the next component.
k -= 1
vector[k] += 1
s += coeff[k]
# Tests
coeff = 150, 20, 17
# Create a list
solns = [v for v in linear_sum(800, 1000, coeff)]
print(len(solns))
# Generate solutions one by one and verify that they give the correct sum
for s, vector in linear_sum(990, 1000, coeff):
assert s == sum(u*v for u, v in zip(coeff, vector))
print(s, vector)
import math
def allSolutions(a,b,nums):
if len(nums) == 0:
return []
c = nums[0]
m = max(0,math.ceil(a/c))
M = math.floor(b/c)
if len(nums) == 1:
return [(x,) for x in range(m,M+1)]
solutions = []
for x in range(M+1):
solutions.extend((x,)+s for s in allSolutions(a-c*x,b-c*x,nums[1:]))
return solutions
据我所知,您不希望生成
S
的实际分区,因为这样做没有意义:如果它小于
1000
,它就不是1000
的分区。你知道吗所以我假设您想生成从
0.8S
到S
的所有数字的分区。你知道吗只要做
list(partitions(n))
。对于您的问题:其中
partitions
是您链接到的函数,由David Eppstein发布,我将复制到下面:这里不需要完全分区算法。你可以通过简单的循环找到你想要的数字。如果你有一个固定数量的系数,如问题中所给出的,那么你可以只使用几个
for
循环。如果系数的数目可以变化,那么你需要一个更复杂的解决方案。你知道吗在这里,我找到适合您的模式的数字,范围是990到1000(包括990到1000),以使输出易于管理,因为在800到1000之间有1284个x、y和z的组合。你知道吗
我假设你想用这些解决方案做一些事情,所以我把它们保存在一个列表中以供进一步处理。你知道吗
输出
我想我应该解释一下这段略显神秘的代码:
//
是楼层除法运算符,a // b
返回小于或等于a/b
的最大整数。你知道吗因此
-d // mx
是最大的整数,因此-d/mx
是最小的整数。但是,这有时会产生非正值(当sy
>;=lo
);当出现这种情况时,max
函数确保1是分配给x
的最小值。你知道吗在看到约翰科尔曼的更普遍的解决方案后,我也受到启发写了一个。我的并不像John的那样简洁易读,但是它使用迭代而不是递归,并且使用更少的内存。它的速度也是原来的两倍,虽然比我原来只能处理3个系数的版本慢了大约20%。你知道吗
此代码不是返回列表,而是一个生成器。因此,您可以在生成结果时使用结果,也可以将结果收集到一个列表或其他一些集合中,例如一个
dict
列表,每个列表包含对应于给定和的元组,和作为该列表的键。你知道吗输出
这里是一种递归方法,给定一个下限
a
,一个上限b
,和一个系数列表nums
,返回一个非负整数向量列表,当与相应的系数相乘然后求和时,返回一个介于a
和b
之间的和。函数允许0
作为值。但请注意,例如,整数解(x,y,z)
与x,y,z >= 1
和(x,y,z)
之间有一个简单的一一对应关系溶液
(x,y,z)
与x,y,z >= 0
和代码如下:
例如,
allSolutions(990-187,1000-187,[17,20,150])
产生的86种解决方案基本上与他们在优秀答案中发现的@PM2Ring相同。allSolutions(800-187,1000-187,[17,20,150])
也找到了1284个解决方案。你知道吗相关问题 更多 >
编程相关推荐