2013-07-26 14 views
0

我想運行一個mincut算法(對於一個類),這適用於較小的測試用例,但每當我把一個更大的測試用例在分配問題),我得到這個錯誤:未定義的方法'班'爲零類:Ruby中的NilClass

「(EVAL):1049:未定義的方法`轉移」爲無:NilClass(NoMethodError)」

我懷疑有可能是某些情況下的程序崩潰,但我無法弄清楚。如果有人能幫助我,那會很棒!

a = [[1, 2, 3, 4, 7], [2, 1, 3, 4], [3, 1, 2, 4], [4, 1, 2, 3, 5], [5, 4, 6, 7, 8], [6, 5, 7, 8], [7, 1, 5, 6, 8], [8, 5, 6, 7]] 

mincut = 8 
count = 10 

def clean(a, i, j)      #When collapsing two nodes together, scans 
    z = a[j][0]       #all elements and changes value of second 
    m = a[i][0]       #index to first, i.e. all 2's become 1's. 
    a.each_index do |x| 
     a[x].each_index do |y| 
      if a[x][y] == z 
      a[x][y] = m 
      end 
     end 
    end 
end 

def delete_loops!(a, i)     #scans concatenated array, removes all duplicates of the first element 
    z = a[i].shift 
     a[i].reject!{ |item| item == z} 
    a[i].unshift(z) 
end 

def collapse!(a, i, j)   #collapses two nodes together 
    clean(a, i, j) 
    a[i].concat(a[j])   #concatenates the second array into the first 
    a.delete_at(j)    #deletes second array 
    delete_loops!(a, i) 
end 

def random(a)     #picks random nodes to collapse, and returns their 
    t = rand(a.size)   #positions in the array. 
    s = a[t][1 + rand(a[t].size - 1)] 
    for x in 0..a.size-1 
     if a[x][0] == s 
     s = x 
     break 
     end 
    end 
return t, s 
end 

for x in 0..count do   #repeats the program x amount of times, returns 
    while a.size > 2 do   #the lowest value of the minimum cut. 
     i, j = random(a) 
     collapse!(a, i, j) 
    end 
    size = a[0].size - 1 

    if size < mincut 
     mincut = size 
    end 
end 
puts mincut 

綜上所述程序,它計算的最小切圖,做奔跑的一組量和保留返回的最小割。似乎很麻煩的區域是我的「delete_loops!」函數,它實質上檢查數組以查看是否有任何元素與數組的第一個元素相匹配,然後刪除所述第一個元素的重複項。我使用「shift」和「unshift」方法來做到這一點(通過刪除然後重新插入第一個元素,我沒有刪除過程中的第一個元素)。

我認爲這可能是某種情況導致它崩潰,或者我執行它的方式給我帶來麻煩。有任何想法嗎?

#edit: full error message, from the codecademy scratchpad 

(eval):1122: undefined method `shift' for nil:NilClass (NoMethodError) 
    from (eval):1131:in `collapse!' 
    from (eval):1149 
    from (eval):1146:in `each' 
    from (eval):1146 

#and from my command line try (reading a text file with same array): 

test.rb:29:in 'delete_loops!" : undefined method 'shift' for nil:NilClass <NoMethodError> 
    from test.rb:38:in 'collapse!' 
    from test:rb:56:in 'block in <main>' 
    from test.rb:53:in 'each' 
    from test.rb:53:in '<main>' 
+0

郵政全堆棧跟蹤。 –

+1

顯然,'a'是零,所以我會放入一些斷言來驗證參數是否有意義(a不是零,我在範圍內)。如果斷言失敗,您可以備份以查找問題。 – Fred

+0

當調試這些問題時,我建議使用調試器。它有助於*遍歷代碼並檢查實時值。 – tessi

回答

1

有時,分配給變量i的隨機值是最後一個可能的數組元素。

所以當崩潰!那麼a.delete_at(j)變量i就會指向最後一個元素的索引+1(這就是說沒有元素,因爲它現在超出了縮短數組的範圍)

我想你想要我指向相同的元素,而不管它在陣列中的位置因爲元素j被刪除而改變了,所以...

在delete_at和delete_loops調用之間添加以下遞減!...處理由i指向的數組的情況不再處於相同位置...

a.delete_at(j) 
i -= 1 if i >= j 
delete_loops!(a, i) 

想想吧,如果隨機分配給i和j數量相等你也有一個問題...

,所以你可能要更改來電要崩潰了!...

collapse!(a, i, j) if i != j 
相關問題