Skip to content

Instantly share code, notes, and snippets.

@larryfox
Last active August 29, 2015 14:01
Show Gist options
  • Save larryfox/df4bf7af6ebe947f5f6e to your computer and use it in GitHub Desktop.
Save larryfox/df4bf7af6ebe947f5f6e to your computer and use it in GitHub Desktop.
Merge sort problem sets in Julia and Ruby
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
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