Learning Insertion Sort in Ruby
You are overruning the bounds of your array. The example you were given was assuming 1-indexed arrays, but arrays in ruby are 0-indexed. The first line should be
for j in 1...num.length
Learning Insertion Sort in Ruby
You are overruning the bounds of your array. The example you were given was assuming 1-indexed arrays, but arrays in ruby are 0-indexed. The first line should be
for j in 1...num.length
Insertion sort in Ruby
In the C++
version you have (i = 1; i < length; i++)
. Which means, it will not run the last round where i = length
. That would be out of the array.
In ruby
, because you set the offset of the index to 1
, the last round, you would have i = length
. Hence source[length]
is out of source
, so returns nil
.
1 > nil # source[j-1] > source[j] when j = length
# ArgumentError: comparison of Fixnum with nil failed
Creating Insertion Sort in Ruby
The problem is that pull_position
is not an element of array
. (It's an index.) So array.delete(pull_position)
returns nil
, which is assigned to checked_value
. checked_value < array
... raises the exception, because nil
does not have a method <
.
Instead of array.delete(pull_position)
I expect you want array.delete_at(pull_position)
, though that's not enough to fix the code.
The problem was easy to spot when I ran the code and got this exception:
NoMethodError: undefined method `<' for nil:NilClass
from (irb):39:in `block in insertion_sort'
...
This is valuable information. It tells me the exception occurred when
while checked_value < array[insert_point - 1] and insert_point >= 0 do
was executed and that checked_value
was equal to nil
. So it was then just a matter of seeing where checked_value
was last assigned a value (nil
), and bingo!
implement shell sort by ruby
I referenced Shell Sort in here : Shell Sort - Wikepedia, and from that I have understood your algorithm is wrong. Iteration of gap sequence is alright, I mean you iterate only upto d/2 == 1
.
But for a gap, let's say 2, you simply iterate from 0
to list.length-2
and swap every j
and j+2
elements if list[j]
is greater than list[j+2]
. That isn't even a proper insertion sort, and Shell Sort requires Insertion sorts on gaps. Also Shell Sort requires that after you do an x gap sort, every xth element, starting from anywhere will be sorted (see the example run on the link and you can verify yourself).
A case where it can wrong in a 2 gap sort pass :
list = 5,4,3,2,1
j = 0 passed :
list = 3,4,5,2,1
j = 1 passed :
list = 3,2,5,4,1
j = 2 passed
list = 3,2,1,4,5
After it completes, you can see that every 2nd element starting from 0 isn't in a sorted order. I suggest that you learn Insertion Sort first, then understand where and how it is used in Shell Sort, and try again, if you want to do it by yourself.
Anyway, I have written one (save it for later if you want) taking your method as a base, with a lot of comments. Hope you get the idea through this. Also tried to make the outputs clarify the how the algorithm works.
def shell_sort(list)
d = list.length
return -1 if d == 0
# You select and iterate over your gap sequence here.
until d/2 == 0 do
d = d / 2
# Now you pick up an index i, and make sure every dth element,
# starting from i is sorted.
# i = 0
# while i < list.length do
0.step(list.length) do |i|
# Okay we picked up index i. Now it's just plain insertion sort.
# Only difference is that we take elements with constant gap,
# rather than taking them up serially.
# igap = i + d
# while igap < list.length do
(i+d).step(list.length-1, d) do |igap|
# Just like insertion sort, we take up the last most value.
# So that we can shift values greater than list[igap] to its side,
# and assign it to a proper position we find for it later.
temp = list[igap]
j = igap
while j >= i do
break if list[j] >= list[j - d]
list[j] = list[j-d]
j -= d
end
# Okay this is where it belongs.
list[j] = temp
#igap += d
end
# i += 1
end
puts "#{d} sort done, the list now : "
puts list.inspect
end
list
end
list = [10,9,8,7,6,5,4,3,2,1]
puts "List before sort : "
puts list.inspect
shell_sort(list)
puts "Sorted list : "
puts list.inspect
How do I write a recursive insertion sort?
This:
arr[0, arr.size - 1]
returns a copy of part of arr
and changes to that copy will not be reflected in arr
. So, your recursive step does nothing useful and your method is equivalent to this:
def recursive_insert(arr)
return arr if arr.size<=1
i=arr.size-1
while arr[i-1]>arr[i] and i>0
arr[i],arr[i-1] = arr[i-1],arr[i]
i-=1
end
arr
end
and that gets the 1 in the right place and that's all.
Related Topics
Double Pipe Symbols in Ruby Variable Assignment
Rails Model, View, Controller, and Helper: What Goes Where
Ruby/Rails - Change the Timezone of a Time, Without Changing the Value
Understanding Ruby and Os I/O Buffering
Iterate Over Ruby Time Object With Delta
Difference Between Gemfile and Gemfile.Lock in Ruby on Rails
Split the String to Get Only the First 5 Characters
Rails Devise: User_Signed_In? Not Working
How to Deal With the Sum of Rounded Percentage Not Being 100
Why Not Use Shared Activerecord Connections For Rspec + Selenium
Convert Array of 2-Element Arrays into a Hash, Where Duplicate Keys Append Additional Values
Ruby: Problem Installing Eventmachine Under Windows 7
How to Understand the Difference Between Class_Eval() and Instance_Eval()
How to Update Ruby on Linux (Ubuntu)
In Ruby Why Won't 'Foo = True Unless Defined(Foo)' Make the Assignment