-2

リスト B=[0,0,0,0,0,0,0,0,0] がありますが、任意の長さにすることができます。

反復によって B に配置できるすべての可能な値を反復しようとしています。いくつかの条件 C が満たされたときに、反復したばかりの要素を「リセット」して、次の項目を 1 つ上げたいと思います。バイナリのように並べ替えます。

000 は 001 になりますが、002 に増やすと条件 C が満たされるため、0 に落として次の列を増やします: 002 は 010 になります。

説明が下手だったらごめんなさい。

だからBはから行くかもしれません

B=[0,0,0,0,1,2,5]
to
B=[0,0,0,0,1,2,6]
to
B=[0,0,0,0,1,2,7]

など。

しかし、条件 C が満たされた場合、次のようにリセットしたいと思います。

B=[0,0,0,0,1,2,96]
...attempt to increment
B=[0,0,0,0,1,2,97]
...attempt to increment
Condition C met
B=[0,0,0,0,1,3,0]

そして、最終的に左端の要素で条件 C に到達するまでこれを行うことができます (1111111 に到達し、それ以上増加できなくなることに相当します)。

コーディングを簡単にするために、条件 C = すべての数値の合計が 100 を超えるとしましょう。

私の試み(agfの要求による):

B=[0,0,0,0,0,0,0,0]
lenB=len(B)

while sum(B)<=100: #I think I have to somehow account for having tried incrementing the far left instead
    B[lenB-1]+=1 #increment last value in B
    while sum(B)>100: #if the sum is greater than 100
        B[lenB-1]=0 #reset the far right element
        B[lenB-2]+=1 #increment the next element
        #but this is wrong because it needs to perform this check again and again
        #for every column, while also checking if B[len-1] or B[len-2] even exists

編集: 実際の条件 C は、単純にSum (B)>100 かどうかをチェックするよりもはるかに複雑です。「if sum(B)>100」をより複雑な条件関数に簡単に置き換えることができるため、これをダミー条件として使用しています。

4

6 に答える 6

3

編集:別のより複雑な問題に対する解決策を作成したようです。コメントで agf によって明らかにされた問題に対する私の解決策は次のとおりです。

def uphill(initial=None):
    """Yields a tuple of integers. On each iteration, add one to the last column
    . If True is sent then reset the column, and begin iterating the previous
    column, until the first column is matched."""
    b = initial
    column = len(initial)-1
    while True:
        if (yield tuple(b)):
            b[column] = 0
            if column > 0:
                column -= 1
                b[column] += 1
            else:
                yield None
                raise StopIteration
            yield None
        else:
            b[column] += 1

gen = uphill([1, 2, 0])
for b in gen:
    print(b)
    if sum(b) >= 4:
        gen.send(True)

私たちに与えること:

(1, 2, 0)
(1, 2, 1)
(1, 3, 0)
(2, 0, 0)
(3, 0, 0)
(4, 0, 0)

古い解決策:

ジェネレーターとあまり知られていない を使用して、非常にエレガントなソリューションを作成できますgenerator.send()

def waterfall(columns):
    """Yields a tuple of integers. On each iteration, adds one to the last list
    item. The consumer can send column numbers to the waterfall during iteration
     - when this is done, the specified column is reset to 0 and the previous 
    column is incremented. When the first column is reset, the iterator ends."""
    b = [0]*columns
    while True:
        reset = (yield tuple(b))
        if not reset == None:
            while not reset == None:
                b[reset] = 0
                if reset > 0:
                    b[reset-1] +=1
                else:
                    yield None
                    raise StopIteration
                reset = (yield None)
        else:
            b[-1] += 1

gen = waterfall(3)
for b in gen:
    print(b)
    if b[2] >= 3:
        gen.send(2)
    if b[1] >= 2:
        gen.send(1)
    if b[0] >= 1:
        gen.send(0)

これにより、次のことがわかります。

(0, 0, 0)
(0, 0, 1)
(0, 0, 2)
(0, 0, 3)
(0, 1, 0)
(0, 1, 1)
(0, 1, 2)
(0, 1, 3)
(0, 2, 0)
(1, 0, 0)

これらの条件は喜んで何にでも変更できます。選択した条件が満たされたときに、リセットしたい列のインデックスをジェネレーターに送信するだけです (これにより、その上にある列が自動的に 1 つ増えます)。最後の列がリセットされると、ジェネレーターが終了します。

gen.close()また、最後の列に到達する必要なく、いつでも停止するために使用できることも注目に値します。(gen.send(0)は と同じgen.close())。

別の条件の例:

gen = waterfall(2)
for b in gen:
    print(b)
    if sum(b) >= 3:
        gen.send(1)
    if b[0] >= 3:
        gen.send(0)

私たちに与えること:

(0, 0)
(0, 1)
(0, 2)
(0, 3)
(1, 0)
(1, 1)
(1, 2)
(2, 0)
(2, 1)
(3, 0)
于 2012-04-17T19:04:45.310 に答える
1
def increment(box, condition):
    # last index in the list
    maxindex = index = len(box) - 1
    while True:
        # so you can see it's correct
        print box
        # increment the last digit
        box[-1] += 1
        # while the overflow condition is True
        while condition(box):
            # reset the current digit
            box[index] = 0
            # and move to the next index left
            index -= 1
            # if we're past the end of the list
            if index < 0:
                # stop
                return
            # increment the current digit
            box[index] += 1
        # back to the rightmost digit
        index = maxindex

increment([0] * 3, lambda box: sum(box) > 4)
于 2012-04-17T18:17:17.683 に答える
0

これは、予想どおり、増分の問題に対処しているようです。

b=[0,0,0,0,0,0,0,1,7]

def incr(arr, condition, pred):
   arr[-1] += 1
   element = -1
   while condition(arr) > pred:

      if arr[element]:
         arr[element] = 0
         arr[element-1] += 1
      else:
         element -= 1
      if abs(element) == len(arr):
         break
   return arr

print b
for i in xrange(0,10):
   b = incr(b, sum, 15)
   print b

関数は、リストと関数条件(たとえば、合計)、および増分が引き継がれるポイントを受け入れます。

したがって、sum(15)の例では次のような結果が返されます。

>>> 
[0, 0, 0, 0, 0, 0, 0, 1, 7]
[0, 0, 0, 0, 0, 0, 0, 1, 8]
[0, 0, 0, 0, 0, 0, 0, 1, 9]
[0, 0, 0, 0, 0, 0, 0, 1, 10]
[0, 0, 0, 0, 0, 0, 0, 1, 11]
[0, 0, 0, 0, 0, 0, 0, 1, 12]
[0, 0, 0, 0, 0, 0, 0, 1, 13]
[0, 0, 0, 0, 0, 0, 0, 1, 14]
[0, 0, 0, 0, 0, 0, 0, 2, 0]
[0, 0, 0, 0, 0, 0, 0, 2, 1]
[0, 0, 0, 0, 0, 0, 0, 2, 2]
于 2012-04-17T18:33:37.370 に答える
0

これはあなたが望むことをしますか?

B=[0,1,0]

def check(ll,callback):
    """
    This function only works if you 
    increment the last element in the list.
    All other incrementing is done in this function.
    """
    for idx in reversed(range(len(ll))):
        if(callback(ll)):
            ll[idx]=0
            ll[idx-1]+=1
        else:
            break  #this index wasn't updated, so the next one won't be either.

    #a check to see if every element is 1
    return all(map(lambda x: x==1,ll))

def checksum(ll):
    return True if sum(ll)>100 else False

count=0
while True:
    count+=1
    B[-1]+=1
    if(check(B,checksum)): break
    print B

print B   # [1,1,1]
print count

この例でも、[1,1,1] の前に 5000 回以上の反復を実行します。

編集

break最後の反復中にリストが変更された場合にのみリストをチェックする必要があるため、簡単なステートメントを追加しました。

于 2012-04-17T18:23:36.690 に答える
0

コンパクトだが非効率的なソリューション

条件が数字に固有でない場合は、LattyWare に似たソリューションを使用してみてください。ただし、フィルターを使用して、予測された結果のみを提供します。

(a, b, c)にマッピングする述語関数のリストがある場合bool

for a, b, c in ((a, b, c) for a in range(2) for b in range(4) for c in range(3)):
    if all [p(a,b,c) for p in predicates]:
        yield a, b, c

個々の数字に妥当な初期境界を設定できない場合、これは受け入れられなくなることに注意してください (検索スペースが大きくなりすぎます)。

于 2012-04-17T18:28:45.140 に答える
0

リスト内包表記を使用してこれを行うことができますrange()(ここでは小さな値を使用して、出力が非常に大きくなるのを防ぎます)。

>>> [(a, b, c) for a in range(2) for b in range(4) for c in range(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), (0, 3, 0), (0, 3, 1), (0, 3, 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), (1, 3, 0), (1, 3, 1), (1, 3, 2)]

最初に大きなリストを生成するのではなく、それをループしたい場合は、ジェネレーター式を使用すると、必要に応じて項目のみが作成されることに注意してください。

for a, b, c in ((a, b, c) for a in range(2) for b in range(4) for c in range(3)):
    ...

また、Python 2.x では、リストではなくジェネレーターを取得するxrange()のではなく、使用する必要があることに注意してください。range

于 2012-04-17T18:13:20.170 に答える