2013-07-09 4 views
0

Я реализовал алгоритм для подсчета инверсии массива (который также объединяет-sots массив), но для того, чтобы сделать его более аккуратным, я хочу сортировать и подсчитывать выходные данные.Вызов частного метода

Метод * count_and_sort * возвращает массив [number_of_inversions, [sorted_array]]. Методы инверсий и * merge_sort * должны вернуться number_of_inversions и [sorted_array] отдельно, но вместо этого я получаю NoMethodError

Что я пропустил?


class Array 

    def inversions 
     count_and_sort[0] 
    end 

    def merge_sort 
     count_and_sort[1] 
    end 

    def merge_sort! 
     replace merge_sort 
    end 

private 

    def count_and_sort 
     return [0, self] if self.size <= 1 
     left, right = partition.with_index{ |value, index| index < self.size/2} 
     left = left.count_and_sort 
     right = right.count_and_sort 
     merged = merge(left[1], right[1]) 

     [left[0] + right[0] + merged[0], merged[1]] 
    end 

    def merge(left, right) 
     inversions = 0 
     merged = [] 
     until left.empty? || right.empty? 
      if left.first < right.first 
       merged << left.shift 
      else 
       merged << right.shift 
       inversions += left.size 
      end 
     end 

     merged += left += right 
     [inversions, merged] 
    end 
end 

p [*1..20].shuffle.inversions 

Я попытался заменить инверсий с

def inversions 
    result = self.send(:count_and_sort) 
    result[0] 
end 

, но результат был тот же.

PS любая другая критика и комментарии приветствуются;)

+1

Можете ли вы разместить точный вывод ошибки, пожалуйста? – tessi

+0

main.rb: 20: in 'count_and_sort': private method 'count_and_sort', вызываемый для [9, 6, 4, 1, 12, 14, 16, 15, 5, 3]: массив (NoMethodError) \t из основного. rb: 4: in 'inversions' \t от main.rb: 44: in '

' – Konstantin

ответ

2

Ошибка внутри метода count_and_sort, как сообщение об ошибке говорит:

... in 'count_and_sort': private method 'count_and_sort' called for ... 

Неправильные линии:

left = left.count_and_sort 
right = right.count_and_sort 

Частные методы в Ruby нельзя вызывать с явным приемником, их нужно называть неявно на self. Таким образом, вы можете либо защитить метод count_and_sort, либо позвонить ему, используя send по адресу left и right. В этом случае я бы предложил первое.

+0

Хороший блогпост на эту тему. http://weblog.jamisbuck.org/2007/2/23/method-visibility-in-ruby –

+0

Отлично, спасибо большое! 'left = left.send (: count_and_sort)' 'right = right.send (: count_and_sort)' работает отлично. – Konstantin