[Courses] [Ruby] Lesson 0: Homework
Laurel Fan
laurel.fan at gmail.com
Sat Nov 19 05:18:34 EST 2005
On 11/14/05, Anne G <anne at wjh.harvard.edu> wrote:
Hi Anne!
Great example implementation of quicksort. It shows off one of the
unique features of ruby, which is the block syntax (the { |i| i < m }
stuff). There's more about blocks in the book, and this interview
with the language designer (Yukihiro "Matz" Matsumoto) gives a little
more background:
http://www.artima.com/intv/closures.html
> def quicksort( xs )
> puts "Iterations, array size = "
> puts xs.size
> puts "Print the array"
> puts xs
> return xs if xs.size <= 1
> m = xs[0] # Split-Element
> quicksort(xs.select { |i| i < m } ) +
> xs.select { |i| i == m } +
> quicksort(xs.select { |i| i > m } )
> end
> puts "Final array"
> puts quicksort([13, 11, 74, 69, 0])
> puts "hello we are done"
>
> Here is the comment
> -----------------------------------------------------------------
> line by line:
>
> return xs if xs.size <= 1
>
>
> If the size is 1 or 0, we just return the array; it's already sorted
>
> m = xs[0]
>
> Here we choose an arbitrary "Pivot" element.
> This can be any element of the array. In this case we choose
> the first.
>
> quicksort(xs.select { |i| i < m } ) +
> xs.select { |i| i == m } +
> quicksort(xs.select{ |i| i > m } )
>
> This is a little more complicated. First, let's figure out
> what those selects do. The first one selects all elements
> less than the pivot. The second selects all elements equal
> to the pivot. The final one selects all elements greater
> than the pivot. Let's modify this and use some temp variables.
>
> less = xs.select { |i| i < m }
> equal = xs.select { |i| i == m }
> more = xs.select { |i| i > m }
>
> quicksort( less ) +
> equal +
> quicksort( more ) )
>
>
> In other words, we're returning a list of all the elements
> less than the pivot, sorted, then all those equal, then all
> those greater, sorted. This is classic divide-and-conquer
> recursion. Quicksort is applied to ever smaller lists until
> we use it on lists of one or zero elements, and we hit the
> terminating condition.
>
> -----------------------------------------------------------
> the xs.select is equivalent to the find function in matlab.
>
> xs.select { |i| i < m }
> |i| must mean for each element of xs compare it to m
> what is confustin to me is I usually use i as an index, but
> since m=xs[0], i must be an array element.
Yes, you're right. If you use matlab, you might like all the
functions on Enumerable (like select), since they kind of resemble
doing vector operations.
> -----------------------------------------------------------
> I have never used recursion like this, it is very efficient,
> but I wonder about readability!
Sometimes I find it more readable to use the long form, such as:
xs.select do |i|
i < m
end
In any case, I think it takes some getting used to. It's not as
immediately intuitive as some concepts (like if/else). I think there
are lots of cases when it's more readable than doing it without it.
When you do a sort in C, and want to define your own comparison
function, you have to define a function separately and make a function
pointer; in other OO languages like C++ and Java, the same thing
might require making a completely different object.
--
Laurel Fan
http://dreadnought.gorgorg.org
More information about the Courses
mailing list