2011-12-14 18 views
3

私は一般的にはPythonとプログラミングの初心者です。私は配列内の隣接する要素を検索し、floodfillアルゴリズムのように互いに0.05以内の値を持つ関数を探す関数を書いています。唯一の違いは、関数が何回実行されたかを数えることになると私は何か愚かなことをしていることです(私が考えている要素の数がわかります)ので、カウンタ値が間違っています。このコードは、互いに0.05以内で隣接する要素を見つけることになります。ちょうどカウントが面白いです。テストケース再帰関数のカウンタ

配列= [5,1,1,3,4]、[4,5,6,2,5]、[5,8,5ためだから

def floodcount (x,y,array,value,count=0):  #akin to a bucket fill in paint, finds the area instead 

    nrows = len(array)-1   #rows of the image 
    ncols = len(array[0])-1  #columns of the image 
    diff = array[x][y] - value 
    if (diff < 0.00) or (diff > 0.05): # the base case, finding a diff more than 0.05 or less than 0 is like finding a boundary 
     return 0 

    count = count +1 
    print 'count1 ',count 

    array[x][y] = -5 # so we do no calculate this pixel again 
    #print "[",x,",",y,"]" 
    if x > 0: 
     #print '1'# if not the first elemnet then can go back, this makes sure that x is within the array all the time 
     floodcount (x-1,y,array,value,count) 
    if y > 0: 
     #print '2' 
     floodcount (x,y-1,array,value,count) 
    if x < nrows: 
     #print '3' 
     floodcount (x+1,y,array,value,count) 
    if y < ncols: 
     #print '4' 
     floodcount (x,y+1,array,value,count) 
    if x > 0 and y > 0: 
     #print '5' 
     floodcount (x-1,y-1,array,value,count) 
    if x < nrows and y < ncols: 
     #print '6' 
     floodcount (x+1,y+1,array,value,count) 
    if x <nrows and y > 0: 
     #print '7' 
     floodcount (x+1,y-1,array,value,count) 
    if x > 0 and y < ncols: 
     #print '8' 
     floodcount (x-1,y+1,array,value,count) 

    print 'count2 ',count  
    return count 

、 5,9] X = 0、Y = 0

OUTPUT

COUNT1 1 COUNT1 2 COUNT1 3 COUNT1 4 COUNT1 5 COUNT2 5 COUNT2 4 COUNT2 3 COUNT1 3 COUNT2 3 COUNT2 2 COUNT2 1

あなたが何かを見ることができるように怪しいです:P は私が間違っているの何誰を指摘することはできますか?どんな助けもありがとう。私の解明(ここでは下)正確に適切ではありません。あなたが取得

+0

実際には行と列の数が格納されていないため、nrowsとncolsの名前を変更する必要があると思います(回答しようとすると混乱してしまいます)。初期化から-1を削除し、ifステートメントロジックを変更します。 – colithium

答えて

2

今解かカウントの問題に加えて:

あなたは毎回すべての再帰呼び出しを行うと、ちょうどif x < 0 or y < 0 or x > nrows or y > ncolsと関数の先頭に配列の境界を確認することでif文の数を減らすことができます。

#akin to a bucket fill in paint, finds the area instead 
def floodcount (x,y,array,value,count=0): 
    nrows = len(array)-1   #rows of the image 
    ncols = len(array[0])-1  #columns of the image 
    if x < 0 or y < 0 or x > nrows or y > ncols: 
     return count 

    diff = array[x][y] - value 
    # the base case, finding a diff more than 0.05 or less than 0 is like finding a boundary 
    if (diff < 0.00) or (diff > 0.05): 
     return count 

    count = count +1 
    print 'count1 ',count 

    array[x][y] = -5 # so we do no calculate this pixel again 
    #print "[",x,",",y,"]" 

    count = floodcount (x-1,y,array,value,count) 
    count = floodcount (x,y+1,array,value,count) 
    count = floodcount (x+1,y,array,value,count) 
    count = floodcount (x,y-1,array,value,count) 

    count = floodcount (x-1,y-1,array,value,count) 
    count = floodcount (x+1,y+1,array,value,count) 
    count = floodcount (x+1,y-1,array,value,count) 
    count = floodcount (x-1,y+1,array,value,count) 

    print 'count2 ',count  
    return count 
+0

ありがとうございます:) –

2

結果は

UPDATEが期待されています。 (啓蒙のためにベンに感謝)

count引数は、再帰呼び出しに値でを渡され、参照によって ない(それでも、私の解決策の提案は正しいです)。つまり、サブ呼び出しでのインクリメントは、現在の関数 (=ローカル関数変数)のcount変数には影響しません。

あなたはいずれかを使用して、グローバル変数で希望の結果を得ることができます。

count = 0 
def floodcount (x,y,array,value): 
    global count 
    ... 

またはラッピングクラスでカウンタを有することにより(オブジェクトは参照によって渡されます):

class CounterClass: 
    cnt = 0 

def floodcount (x,y,array,value, counter): 
    ... 
    counter.cnt += 1 
    ... 

かelse:関数によって生成されたカウンタを返します。

count = floodcount(x+1, y-1, array, value, count) 
+1

これは厳密には真実ではありません。 Pythonではすべてが参照渡しされます。 'count + = 1'は' count'で参照されるオブジェクト( 'count'が整数)を変更しないので、代わりに新しい整数を作成し、それに' count'をバインドします。したがって、すべてのネームバインディングと同じように、ローカルスコープでのみ効果があり、同じことを指す別の参照には影響しません。これは、**あなたが整数を変更するために何もできない**があるからです。古い整数の操作から新しい整数オブジェクトを作成することしかできません。 – Ben

+0

enlightmentをありがとう – gecco

+0

グローバルに働く数を宣言しています:)ありがとう –

0

xyの両方が0より大きい場合は、floodcount()を2回実行します。それはあなたが欲しいものですか?配列内の要素ごとにfloodcountを1回だけ実行したいと思うようです。その場合は、だから、floodcount()は新しいcount値を返しているだけではなく、if

if x > 0: 
    floodcount (x-1,y,array,value,count) 
elif y > 0: 
    floodcount (x,y-1,array,value,count) 

#elif all the rest 
3

if/elifを使用するようにコードを変更します。あなたがから開始することを現在countを供給し、再帰的にfloodcountを呼び出し、それ

count = floodcount(x+1, y-1, array, value, count) 
+0

私は、それは出力を与えた –

+0

'return 0'を' return(diff <0.00)または(diff> 0.05) 'の' return counter' に変更したいと思います。 – sevenforce

+0

は私がすることを試みた –

1

:で

floodcount(x+1, y-1, array, value, count) 

:しかし、あなたのような行を交換して/それを使用:)

を保存することはありません忠実にそれが完了したときに持っていたcountを返します。その後、あなたは無視し、同じcountを持つ次の再帰呼び出しに進み、最初の再帰呼び出しに渡します。すべての再帰呼び出しをcount = floodcount(...)に変更してみてください。

+0

:)ご協力いただきありがとうございますが、それは、出力に COUNT1 1 COUNT1 1 COUNT1 1 COUNT1 1 COUNT1 1 COUNT2 0 COUNT2 0 COUNT2 0 COUNT1 1 COUNT2 0 COUNT2を与えました0 count2 0 (グローバルなものとして宣言されているのは、geccoが提案した通りです)。しかし、Geccoの記事に関するあなたの以前のコメントから、それはうまく動作しなかったようですね?どのような提案や私はちょうど何の作品に固執する必要がありますか? –

+0

@ Elegant_Cow:この関数を2回以上呼び出す必要があり、それを0にリセットすることを忘れてしまった場合、グローバル変数は失敗します。提案を試しても**にcount **を渡していますか? – Ben

+0

作品は今、ありがとうございます。今私はグローバル変数を持つ落とし穴を知っています:) –