Insertion sort is undoubtedly the easiest to understand-to-understand and easiest to code-to-code sorting method, requiring but one line of Ruby code. It seems overkill in the extreme to define a class with instance variables and multiple instance methods. I have written a single method insertion_sort.
If desired ifit could be written as a module method in a module that could be required as needed. For example:Assuming you wished to compare sorting methods (considering that the more efficient built-in methods Array#sort, Enumerable#sort and Enumerable#sort_by would be the methods of choice for general sorting needs) you might create a module such as the following.
module Sorting_MethodsSortingMethods
def self.insertion_sort(arr)
...
end
def self.bubble_sort(arr)
...
end
...
end
The method would then be invoked
sorted = SortingMethods.insertion_sort(arr)
This is analogous to the use of the built-in Math module, which contains module methods only, methods that would serve as functions (which are not invoked on receivers) in other languages.
The method insertion_sort can be written is as follows.
arr = 8.times.map { rand[30] }
#=>insertion_sort [8, 29, 10, 20, 26, 5, 20, 2]
insertion_sort(arr)
#=> [2, 5, 8, 10, 20, 20, 26, 29]
Array#insert
inserts a given object into self before the element at a given index. If that index equals the size theof (the array that is) self, the element is inserted after the last element of self.
Array#bsearch_index returns the index of the element of sorted before which a given object is to be inserted in order to keep sorted sorted. nil is returned if the given object is greater than the last element of sorted (hence the need for || sorted.size). See also Array#bsearch for details.
Note that the argument is not mutated (modified).
The easiest way to demonstrate the calculations is to run the code after having salted it with puts statements. I will write the code in a simpler way that effectively performs the same operations.
arr = [8, 29, 10, 20, 26, 5, 20, 2]
sorted = []
arr.each do |o|
puts "\no = #{o}, sorted = #{sorted}"
idx = sorted.bsearch_index { |e| e >= o }
puts "idx from bsearch initially = #{ idx.nil? ? 'nil' : idx }"
idx = idx || sorted.size
puts "idx after 'idx || sorted' = #{idx}"
sorted.insert(idx, o)
puts "sorted after sorted.insert(#{idx}, #{o}) = #{sorted}"
end
#=> [8, 29, 10, 20, 26, 5, 20, 2]