Add min/max/min_by/max_by optional argument support

Per issue #2099 - adds support for an optional argument which indicates that the method should return an array of values corresponding to the top n values. This is currently implemented as sort.first(n) or sort.last(n).reverse and should be refactored to something that is O(n) memory rather than O(elems).

I also performed some heavy refactoring of the Enumerable min/max/etc code to eliminate redundant code and to attempt to make it easier to replace the implementations of each case as needs warrant.