2

課題は、合計が N に等しい N 未満の数の可能な組み合わせをすべて見つけることでした。たとえば、N が次の場合:

  • 2
    • 1+1 - 片道
  • 3
    • 2+1
    • 1+1+1 - 2 つの方法
  • 4
    • 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:
                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
  1. 次に、コードを次のように変更しました。これは、N = 6 以下で機能します。
N=6
for e in drange(0,N,1):
    if N-e*5>=0:
        C0 = N-e*5
        for d in drange(0,N,1):
            if C0-d*4>=0:
                C1 = C0-d*4
                for c in drange(0,N,1):
                    if C1-c*3>=0:
                        C2 = C1-c*3
                        for b in drange(0,N,1):
                            if C2-b*2>=0:
                                C3 = C2-b*2
                                for a in drange(0,N,1):
                                    if C3-a*1==0:
                                        if sum([e,d,c,b,a])!=1:
                                            print e,d,c,b,a                            
                            else: break
                    else:break
            else:break
    else:break
  1. 次のバージョンでは、数値を追跡し、計算スペースを節約するために配列が組み込まれています。
N=6
Nums = drange2(6-1,-1,-1)
Vals = [0]*6
Vars = [0]*6
for Vars[0] in drange(0,N,1):
     if N-Vars[0]*Nums[0]>=0:
         Vals[0] = N-Vars[0]*Nums[0]
         for Vars[1] in drange(0,N,1):
             if Vals[0]-Vars[1]*Nums[1]>=0:
                 Vals[1] = Vals[0]-Vars[1]*Nums[1]
                 for Vars[2] in drange(0,N,1):
                     if Vals[1]-Vars[2]*Nums[2]>=0:
                         Vals[2] = Vals[1]-Vars[2]*Nums[2]
                         for Vars[3] in drange(0,N,1):
                             if Vals[2]-Vars[3]*Nums[3]>=0:
                                 Vals[3] = Vals[2]-Vars[3]*Nums[3]
                                 for Vars[4] in drange(0,N,1):
                                     if Vals[3]-Vars[4]*Nums[4]==0:
                                         if sum([Vars[0],Vars[1],Vars[2],Vars[3],Vars[4]])!=1:
                                             print Vars                           
                             else: break
                     else:break
             else:break
     else:break
  1. 次に、Nが100の場合にこのコードを機能させることを考え、再帰的にしました...
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
  1. 問題: 1000000 回以上のメソッド呼び出しのために時間がかかりすぎるため、すべてを入力せずに以前のカスケード効果を作成する反復を行う方法はありますか? for ループと if ステートメントを繰り返し含む再帰関数を作成する方法について、Web サイトなどを検索しましたが、この特定の関数では運がありませんでした。知恵を貸してください -- Shaha3
4

2 に答える 2

5

なぜ再帰的にしたいのですか?

>>> 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とともに大きくなります!そのため、大きな数の場合は時間がかかります。

于 2012-07-13T04:41:18.307 に答える
2

整数分割の問題について話していると思います(wiki: http: //en.wikipedia.org/wiki/Partition_ (number_theory ))これは反復的な方法でも再帰的な方法でも実行できますが、深さの制限がある可能性があります。再帰的方法。これが私の実装です


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'
于 2012-07-13T04:42:37.750 に答える