2012-10-11 144 views
2

圈想通過遞歸做到以下幾點,這樣我可以改變「爲」循環次數:變量與遞歸

n = 5 
out = [] 
for i in range(n): 
    for j in range(i,n): 
     for k in range(j,n): 
      out.append([i,j,k]) 

要返回

out = [[0 0 0] 
     [0 0 1] 
     [0 0 2] 
     [0 0 3] 
     [0 0 4] 
     [0 1 1] 
     [0 1 2] 
     [0 1 3] 
     [0 1 4] 
     [0 2 2] 
     [0 2 3] 
     [0 2 4] 
     [0 3 3] 
     [0 3 4] 
     [0 4 4] 
     [1 1 1] 
     [1 1 2] 
     [1 1 3] 
     [1 1 4] 
     [1 2 2]...] 

例如

def Recurse(n, p): 
    # where p is the number of for loops 
    some magic recursion 
    return out 

我看了一些其他的遞歸問題,但努力找到解決方案。

回答

4

而不是使用遞歸的,使用itertools.product(),嵌套for循環在發電機表達這相當於:

>>> import itertools 
>>> list(itertools.product(range(3), repeat=2)) 
[(0, 0), (0, 1), (0, 2), (1, 0), (1, 1), (1, 2), (2, 0), (2, 1), (2, 2)] 
>>> list(itertools.product(range(3), repeat=3)) 
[(0, 0, 0), (0, 0, 1), (0, 0, 2), (0, 1, 0), (0, 1, 1), (0, 1, 2), (0, 2, 0), (0, 2, 1), (0, 2, 2), (1, 0, 0), (1, 0, 1), (1, 0, 2), (1, 1, 0), (1, 1, 1), (1, 1, 2), (1, 2, 0), (1, 2, 1), (1, 2, 2), (2, 0, 0), (2, 0, 1), (2, 0, 2), (2, 1, 0), (2, 1, 1), (2, 1, 2), (2, 2, 0), (2, 2, 1), (2, 2, 2)] 

編輯:沒有意識到,這實際上不是一個笛卡爾乘積自內部循環使用外部變量開始的範圍,這裏是一個可能性,但效率不高,因爲它可能是因爲它會產生額外的價值和需要檢查每個值是有效的:

def nested_loops(n, num_loops): 
    prod = itertools.product(range(n), repeat=num_loops) 
    for item in prod: 
     if all(item[i] <= item[i+1] for i in range(num_loops-1)): 
      yield item 

>>> list(nested_loops(3, 2)) 
[(0, 0), (0, 1), (0, 2), (1, 1), (1, 2), (2, 2)] 
>>> list(nested_loops(3, 3)) 
[(0, 0, 0), (0, 0, 1), (0, 0, 2), (0, 1, 1), (0, 1, 2), (0, 2, 2), (1, 1, 1), (1, 1, 2), (1, 2, 2), (2, 2, 2)] 
+0

編曲你打我吧! :) –

+0

我敢打賭,這是他必須使用遞歸的作業... –

+1

儘管OP的期望輸出不是笛卡兒乘積,但沒有(1,0,0)。檢查範圍參數。 – DSM

2

@DSM有一個更好的答案(但在評論)

但是這裏有一個簡單的遞歸解決方案,萬一有人正在努力解決它

def f(n, p, start=0): 
    if p==0: 
     yield [] 
    else: 
     for i in range(start, n): 
      for j in f(n, p-1, i): 
       yield [i]+j