Python 将for循环和if语句的递归函数转换为迭代函数
挑战是找到所有可能的小于N的数字组合,其和等于N。 例如,当N等于:Python 将for循环和if语句的递归函数转换为迭代函数,python,recursion,if-statement,for-loop,iteration,Python,Recursion,If Statement,For Loop,Iteration,挑战是找到所有可能的小于N的数字组合,其和等于N。 例如,当N等于: 二, 1+1-1路 三, 2+1 1+1+1-2路 四, 3+1 2+2 2+1+1 1+1+1+1-4路 等等 现在用python创建它,为了理解我首先起草的代码模式: N=5 for d in drange(0,N,1): if N-d*4>=0: for c in drange(0,N,1): if N-d*4-c*3>=0:
- 二,
- 1+1-1路
- 三,
- 2+1
- 1+1+1-2路
- 四,
- 3+1
- 2+2
- 2+1+1
- 1+1+1+1-4路
N=5
for d in drange(0,N,1):
if N-d*4>=0:
for c in drange(0,N,1):
if N-d*4-c*3>=0:
for b in drange(0,N,1):
if N-d*4-c*3-b*2>=0:
for a in drange(0,N,1):
if N-d*4-c*3-b*2-a*1==0:
if sum([d,c,b,a])!=1:
print d,c,b,a
else: break
else:break
else:break
N=48
Nums=drange2(N-1,-1,-1)
VAL=[0]*N
变量=[0]*(N-1)
计数=0
def sumCombos(编号,i):
如果i==0:
全局计数
对于x范围(0,i+2,1)内的变量[i]:
z=变量数[i]*Nums[i]
如果z>=0:
Vals[i]=z
sumCombos(数字,i+1)
其他:休息
如果i=0:
Vals[i]=z
sumCombos(数字,i+1)
其他:休息
elif i==第2个:
对于x范围(0,i+3,1)内的变量[i]:
如果VAL[i-1]-Vars[i]*Nums[i]==0:
计数+=1
sumCombos(N,0)
打印计数
为什么希望它是递归的
>>> from itertools import chain, combinations_with_replacement
>>> n = 7
>>> [i for i in chain.from_iterable(
combinations_with_replacement(range(1, n), k)
for k in range(2, n+1))
if sum(i) == n]
[(1, 6), (2, 5), (3, 4), (1, 1, 5), (1, 2, 4), (1, 3, 3), (2, 2, 3), (1, 1, 1, 4), (1, 1, 2, 3), (1, 2, 2, 2), (1, 1, 1, 1, 3), (1, 1, 1, 2, 2), (1, 1, 1, 1, 1, 2), (1, 1, 1, 1, 1, 1, 1)]
这个问题随着n的增加而增加!所以,对于大数字来说,这需要很多时间 我猜您在谈论整数分区问题(wiki:))它可以通过迭代方式或递归方式完成,尽管递归方法可能有深度限制。下面是我的实现
def partitions(n):
def next(seq):
L = len(seq)
## start from L-2 element, must have at least one element in suffix
for i in range(L-2, -1, -1):
if seq[i-1] and seq[i-1] > seq[i]: break
remainder = n - sum(seq[:i+1]) - 1
return seq[:i] + [seq[i]+1] + [1 for _ in range(remainder)]
start, end = [1 for _ in range(n)], [n]
seq = start
while True:
yield seq
if seq >= end: break
seq = next(seq)
这并没有得到所有的答案(哪里是
(1,1,1,1,1,1,1)
)?@mgilson哦,对了<代码>组合与替换使其工作正常:)
N=48
Nums = drange2(N-1,-1,-1)
Vals = [0]*N
Vars = [0]*(N-1)
count=0
def sumCombos(Number,i):
if i==0:
global count
for Vars[i] in xrange(0,i+2,1):
z = Number-Vars[i]*Nums[i]
if z>=0:
Vals[i] = z
sumCombos(Number,i+1)
else: break
elif i<Number-2:
for Vars[i] in xrange(0,i+1,1):
z = Vals[i-1]-Vars[i]*Nums[i]
if z >=0:
Vals[i]=z
sumCombos(Number,i+1)
else: break
elif i==Number-2:
for Vars[i] in xrange(0,i+3,1):
if Vals[i-1]-Vars[i]*Nums[i]==0:
count+=1
sumCombos(N,0)
print count
>>> from itertools import chain, combinations_with_replacement
>>> n = 7
>>> [i for i in chain.from_iterable(
combinations_with_replacement(range(1, n), k)
for k in range(2, n+1))
if sum(i) == n]
[(1, 6), (2, 5), (3, 4), (1, 1, 5), (1, 2, 4), (1, 3, 3), (2, 2, 3), (1, 1, 1, 4), (1, 1, 2, 3), (1, 2, 2, 2), (1, 1, 1, 1, 3), (1, 1, 1, 2, 2), (1, 1, 1, 1, 1, 2), (1, 1, 1, 1, 1, 1, 1)]
def partitions(n):
def next(seq):
L = len(seq)
## start from L-2 element, must have at least one element in suffix
for i in range(L-2, -1, -1):
if seq[i-1] and seq[i-1] > seq[i]: break
remainder = n - sum(seq[:i+1]) - 1
return seq[:i] + [seq[i]+1] + [1 for _ in range(remainder)]
start, end = [1 for _ in range(n)], [n]
seq = start
while True:
yield seq
if seq >= end: break
seq = next(seq)
# test cases
if __name__ == '__main__':
## test partitions
assert list(partitions(4)) == [[1, 1, 1, 1], [2, 1, 1], [2, 2], [3, 1], [4]]
assert list(partitions(5)) == [
[1, 1, 1, 1, 1],
[2, 1, 1, 1], [2, 2, 1],
[3, 1, 1], [3, 2],
[4, 1],
[5]]
print 'all tests passed'