0

I've implemented algorithm for counting array inversions (which also merge-sots the array) but in order to make it more neat I want to didide sorting and counting outputs.

Method *count_and_sort* returns array [ number_of_inversions, [sorted_array] ]. Methods inversions and *merge_sort* are supposed to return number_of_inversions and [sorted_array] separately, but instead I get NoMethodError

What did I miss?


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

I tried replacing inversions with

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

but result was the same.

PS any other criticism and comments are welcome ;)

Konstantin
  • 55
  • 10
  • 1
    Can you post the exact error output, please? – tessi Jul 09 '13 at 09:09
  • main.rb:20:in 'count_and_sort': private method 'count_and_sort' called for [9, 6, 4, 1, 12, 14, 16, 15, 5, 3]:Array (NoMethodError) from main.rb:4:in 'inversions' from main.rb:44:in '
    '
    – Konstantin Jul 09 '13 at 09:22

1 Answers1

2

The error is inside the count_and_sort method, as the error message says:

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

The wrong lines are:

left = left.count_and_sort
right = right.count_and_sort

Private methods in Ruby can't be called with an explicit receiver, they must be called implicitly on self. Thus you can either make the count_and_sort method protected or call it using send on left and right. In this case I would suggest the former.

toro2k
  • 19,020
  • 7
  • 64
  • 71