Issue
Problem
I am trying to write a method (Array#bubble_sort), that takes in an optional proc argument.
When given a proc, the method should sort the array according to the proc.
When no proc is given, the method should sort the array in increasing order.
Recursively, this works fine without adding a proc, however when given an unknown proc, I cannot find a way to pass it back through as an argument correctly.
Code
class Array
def bubble_sort(&prc)
prc = Proc.new{|a,b| a <=> b} if !prc
self.each_with_index do |ele,idx|
if prc.call(self[idx],self[idx+1]) == 1
self[idx],self[idx+1] = self[idx+1], self[idx]
self.bubble_sort(&prc)
end
end
self
end
end
Test Code
[4, 12, 2, 8, 1, 14, 9, 25, 24, 81].bubble_sort
returns the expected results of [1, 2, 4, 8, 9, 12, 14, 24, 25, 81]
[4, 12, 2, 8, 1, 14, 9, 25, 24, 81].bubble_sort { |a, b| a.to_s <=> b.to_s }
returns a stack level too deep error instead of the expected result of [1, 12, 14, 2, 24, 25, 4, 8, 81, 9]
Solution
The issue is not with your passing of the proc, but rather that is that <=>
works differently on numbers and strings.
When your loop gets to the end of the array, self.idx
is equal to self.length - 1
and self.idx + 1
is equal to self.length
. Calling self[self.length]
on an array will always be nil, because of zero-indexing.
So, you end up calling proc.call(<last element of array>, nil)
The behavior of the spaceship operator differs depending on if you do number <=> nil
or number.to_s <=> nil.to_s
(which is the difference between the two procs you're comparing):
81 <=> nil
# => nil
81.to_s <=> nil.to_s
# => 1
In your case, you don't want any comparison with nil to result in a swap, so you have two options:
You can change the proc to return
nil
if the second element is nil:arr.bubble_sort do |a,b| b.nil? ? nil : a.to_s <=> b.to_s end
You can just skip the comparison altogether if
b
is out-of-bounds:self.each_with_index do |ele,idx| next if idx + 1 == self.length # ... other stuff
Answered By - max pleaner Answer Checked By - Pedro (PHPFixing Volunteer)
0 Comments:
Post a Comment
Note: Only a member of this blog may post a comment.