0

(クラスに対して) mincut アルゴリズムを実行しようとしていますが、これは小さなテスト ケースで機能しますが、より大きなテスト ケースを配置するたびに (最終的に割り当ての問題につながる)、次のエラーが発生します。

"(eval):1049: nil:NilClass の未定義のメソッド `shift' (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!」です。基本的に、配列をチェックして、配列の最初の要素と一致する要素があるかどうかを確認し、最初の要素の重複を削除します。これを行うために「シフト」および「シフト解除」メソッドを使用しました(最初の要素を削除してから再挿入することにより、プロセスの最初の要素を削除しないという問題がありました)。

特定のケースでクラッシュする可能性があるか、実行方法が問題を引き起こしていると思います。何か案は?

    #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>'
4

1 に答える 1

1

場合によっては、変数 i に割り当てられたランダムな値が、可能な最後の配列要素になることがあります。

だから崩壊するとき!a.delete_at(j) を実行すると、変数 i は最後の要素 + 1 のインデックスを指します (これは、短縮された配列の範囲外にあるため、要素がないと言うことです)

要素 j が削除されたために配列内の位置が変更されたという事実に関係なく、 i が同じ要素を指すようにしたいので、...

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
于 2013-07-26T17:17:55.670 に答える