2012-04-17 18 views
-2

リストB = [0,0,0,0,0,0,0,0,0]ですが、任意の長さにすることができます。条件付き反復リストの作成

私は反復によってBに配置できるすべての値を反復しようとしています。条件Cが満たされたとき、私は反復した要素を "リセット"し、次の項目を1つ上にバンプします。バイナリのような並べ替え:

000は001になりますが、私たちはそれを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] 

そして、これを行うことができる、私は最終的に1111111を押すと、あることに(同等の左端の要素に、条件Cを打つまでそれ以上は増やせません)。

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 

EDIT:私の条件Cでの、条件C =すべての数字の合計が100

私の試みを(AGFにより要求される)を超えたとしましょうコーディングが容易さのために

単純にSum(B)> 100かどうかをチェックするよりも、現実はMUCHより複雑です。私は単純に "sum(B)> 100"をより複雑な条件関数に置き換えることができるので、これをダミー条件として使用しています。

+2

あなたは何を試してみましたか? _あなたが解決できない部分を具体的に教えてください。私たちはあなたのコードを書くためのものではありません。 – agf

+0

私はプロセスを適切にループして、私がどこにいるのか、どのように増分するのかを把握する方法がわかりません。あなたが0111111でのやり方と1000000への「リセット」のように、一度に複数のものをリセットする必要がある状況を考慮しなければならないと思うからです。 – AOAOne

+0

@agf上記の私の要求を要求通りに追加しました – AOAOne

答えて

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回の反復を介して実行

チェックすることが必要なだけであるようEDIT

は、単純なbreak文を追加しました最後の反復中に変更されている限り、リストします。

+0

はい、私はちょうどループ内に小切手とB [-1] + = 1の部分をまとめなければならないと思います。一番左の列を更新しようとしたときに、どのようにして最終的な終了条件を設定することができますか? – AOAOne

+0

恐らく更新される最後の要素はリストの最初の要素なので、forループの後で、終了条件が満たされているかどうかを確認し、checkから何らかの値を返すことができます。 – mgilson

+0

私は彼の質問を明確にしたので、私の心が変わった。私はこれが基本的に正しいアプローチだと思う。 – agf

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を使用したいと思うことに注意してください。

+0

これは、条件が数字に固有の場合にのみ機能します。例えば。 'B <= 5 '。例えばうまくいきません。 'sum(list)> = 100'となります。 – cmh

+0

@agf彼は宿題ではないと言っているので、そうする理由はありません。 –

+0

私の条件Cは実際にはsum(B)> 100よりはるかに複雑ですが、この質問をするのは簡単に確認できるダミー条件です。私の問題は、リストを適切にインクリメント/リセットすることにあります。 – AOAOne

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) 
+0

私は自分の質問を編集する必要があると思います - 条件Cは数字に固有ではありません。実際にはBのすべての要素をカプセル化しますが、単純で簡単なので「合計(B)> 100」を選択しました。条件Cが任意であると言えば簡単ですか? – AOAOne

+0

@AOAOneそれは本当に問題ではありません。 'if box [index] == maxval'をチェックするのではなく、あなたの状態が何であるかをチェックするだけです。残りのロジックは同じです。 – agf

+0

それを試してみると、値が繰り返され、リセット条件の範囲を超えているようです。たとえばsum(box)> 10ならば、[0,0,11]のようなものが表示され、いくつかのことが繰り返されます。 – AOAOne

0

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

あなたの条件は、数字、特定されていない場合は、だけで断定結果を提供するためのフィルタと、LattyWareに同様のソリューションを使用してみてください。あなたは、個々の数字にバインドされ、合理的なinitalを置くことができないならば、これは受け入れがたいとなっていること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 

ノートに述語関数マッピング(a, b, c)のリストを持っている場合は

(サーチスペースが大きくなりすぎ) 。あなたが期待しているよう

+0

これは良い方法ではありません。範囲のサイズはどのように分かりますか?述語によっては、大部分のアイテムが有効でないため、これは非常に非効率的である可能性があります。数字のインクリメンタを使用すると、5の後にインクリメントしなければならないことが分かっている場合は、6,7,8などをチェックしないでください。 – agf

+0

私はそれが潜在的に非常に非効率的であると思います。しかし、範囲が狭い時代には優雅です。 – cmh

+0

しかし、述語が非常に複雑/非決定論的である場合、どのような範囲がどうあるべきかをどのように知っていますか? 'sum'の場合、各値の最大値は' sum'ですが、もっと複雑なものはどうでしょうか? – agf

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 

関数は、リストと機能条件(例えば、合計)と増分が引き継がなければならないポイントを受け付けます。

>>> 
[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] 
3

編集:

は、したがって、例えば、和(15)のために、このような結果を返し、私は別の、より複雑な問題への解決策を作成しているように見えます。コメントで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, 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) 
+0

素晴らしいジェネレータの使用+1 –

+0

@JakobBowyerあなたはいくつかのクールなものを行うことができます。また、メインループの構文がはるかに良くなります。すべてのフロー制御ではなく、重要なことに集中することができます。 –

+0

これは一般的なケースでどのようにカプセル化しますか?私またはヘキサパロットの答えのように?私はあなたがリセットを特別なケースにする必要がある場合、これがどれほど有用であるかはわかりません。リセットする数字を知ることができるはずです。リセットするかどうかを伝えるだけです。 – agf

関連する問題