Search code examples
rubyselection-sort

Selection sort setting value in each loop


I am trying to find the smallest element in an array.

I tried to do this with finding_smallest method as follows:

def finding_smallest arr_arg
  # first time returns 3;
  # second time returns 3 again, even though arr_arg doesn't have it.
  p arr_arg    
  arr_arg.each do |el|
    if el < @min
      @min = el
    end
  end
  @min
end

def selection_sort array
  counter = 0
  sorting = ->(arr){
    arr_range = arr[counter..-1]
    smallest = finding_smallest(arr_range)
    p arr_range # first iteration - whole array; second iteration - [1..end of the array]
    p smallest # first iteration: 3, second iteration: 3;
    first_element_in_range = arr_range[0] # for switching indexes of smallest and first in array
    arr_range[arr_range.index(smallest)], arr_range[0] = arr_range[0], arr_range[arr_range.index(smallest)] #switching places
    counter += 1
    sorting.call(arr_range) unless counter == array.length || arr.nil?
  }
  sorting.call(array)
end

@array = [78, 42, 51, 49, 74, 53, 66, 39, 40, 3, 66, 100]
@min = @array[0]
selection_sort(@array)

It returns the smallest element from a previous array. I think the problem is that the each loop doesn't set the value for the second time (or first). What I am doing wrong?


Solution

  • @min plays [here] a role of global variable (main’s instance variable.) Once set, it is never updated, since the minimum would never be touched anymore.

    You might want to update it’s value on each subsequent call:

    def finding_smallest arr_arg
      @min = arr_arg.first
    
      arr_arg.each do |el|
        if el < @min
          @min = el
        end
      end
      @min
    end
    

    In ruby we use Enumerable#reduce for that:

    def finding_smallest arr_arg
      @min = arr_arg.reduce do |min, el|
        el < min ? el : min
      end
    end