2011-12-14 2 views
3

Я новичок в питоне и программировании в целом. Я написал функцию, которая будет искать соседние элементы в массиве и искать значения со значениями в пределах 0,05 друг от друга, как это делает алгоритм наводнения. Единственное различие заключается в том, что я делаю что-то глупое, когда дело доходит до подсчета, сколько времени функция запускается (о чем я думаю, также расскажу, сколько элементов я нашел), поэтому мои значения счетчика ошибочны. Код работает, когда дело доходит до нахождения соседних элементов в пределах 0,05 друг от друга, просто подсчет смешно.Счетчик в рекурсивной функции

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,1,1,3,4], [4,5,6,2,5], [5,8,5, 5,9]] х = 0 и у = 0

ВЫХОД

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 заявлений делать все рекурсивные вызовы каждый раз и просто проверка границ массива в начале функции с if x < 0 or y < 0 or x > nrows or y > ncols.

#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 = 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' с этим. Таким образом, как и при всех привязках имен, он имеет эффект только в локальной области, а не на каких-либо других ссылках на то же самое, что указано в 'count'. Это связано с тем, что ** вы ничего не можете сделать, чтобы изменить целое число, вы можете создавать только новые целые объекты из операций над старыми. – Ben

+0

Хорошо. Спасибо за просвещение – gecco

+0

Объявление count как global работал :) Спасибо –

0

Если x и y оба больше 0, вы будете запускать floodcount() дважды. Это то, что вы хотите? Похоже, вы только хотели бы запустить floodcount один раз за элемент в массиве. Если это так, то изменить код, чтобы использовать if/elif вместо того, чтобы просто 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

Так floodcount() возвращается новое значение count.Но вы никогда не храните его/использовать его :)

Заменить строки:

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

С:

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

Я пробовал это, но он дал результат –

+0

Я думаю, вы хотите изменить 'return 0' на' return counter' в 'if (diff <0.00) или (diff> 0.05)' тоже. – sevenforce

+0

Спасибо за вашу помощь :) –

1

Вы называете floodcount рекурсивно, подавая его текущий 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 , но объявление count как глобального работает отлично (так же, как предложил gecco). Однако из вашего предыдущего комментария к сообщению Gecco кажется, что он не предназначен для работы? Любые предложения или я должен просто придерживаться того, что работает? –

+0

@Elegant_Cow: ну, глобальная переменная будет терпеть неудачу, если вам нужно будет вызывать эту функцию более одного раза, и вы забудете ее сбросить до 0. Вы уверены, что все еще проходили подсчет ** в **, когда вы пробовали мое предложение? – Ben

+0

Работы сейчас, большое спасибо. Теперь я знаю об ошибках с глобальными переменными :) –

Смежные вопросы