Last active
August 29, 2015 14:01
-
-
Save larryfox/df4bf7af6ebe947f5f6e to your computer and use it in GitHub Desktop.
Merge sort problem sets in Julia and Ruby
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
halflength(array::Array) = (1+length(array))>>>1 | |
take(array::Array, n::Int) = array[1:n] | |
drop(array::Array, n::Int) = array[n+1:end] | |
function sortcountinversions(array::Array{Int,1}) | |
length(array) > 1 || return array, 0 | |
n = halflength(array) | |
(left, x) = sortcountinversions(take(array, n)) | |
(right, y) = sortcountinversions(drop(array, n)) | |
(sorted, z) = mergecountsplitinvs(left, right) | |
sorted, x+y+z | |
end | |
function mergesort(array::Array{Int,1}) | |
length(array) > 1 || return array | |
n = halflength(array) | |
left = mergesort(take(array, n)) | |
right = mergesort(drop(array, n)) | |
first(mergecountsplitinvs(left, right)) | |
end | |
function mergecountsplitinvs(left::Array{Int,1}, right::Array{Int,1}) | |
sorted = Int[] | |
count = 0 | |
while length(left) != 0 && length(right) != 0 | |
if first(left) <= first(right) | |
push!(sorted, shift!(left)) | |
else | |
push!(sorted, shift!(right)) | |
count += length(left) | |
end | |
end | |
vcat(sorted, left, right), count | |
end |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class Array | |
def sort_count_inversion | |
return self, 0 unless size > 1 | |
left, x = *self.take(size / 2).sort_count_inversion | |
right, y = *self.drop(size / 2).sort_count_inversion | |
sorted, z = *merge_count_split_inversion(left, right) | |
return sorted, x+y+z | |
end | |
def merge_sort | |
# Base case | |
return self unless size > 1 | |
left = self.take(size / 2).merge_sort | |
right = self.drop(size / 2).merge_sort | |
merge_count_split_inversion(left, right).first | |
end | |
private | |
def merge_count_split_inversion(left, right) | |
ary = [] | |
count = 0 | |
while left.first && right.first | |
if left.first <= right.first | |
ary << left.shift | |
else | |
ary << right.shift | |
count += left.size | |
end | |
end | |
return ary.concat(left).concat(right), count | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment