Created
July 20, 2015 18:29
-
-
Save asterite/3a83aabc9fba627c4dcc to your computer and use it in GitHub Desktop.
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
require "benchmark" | |
################################ Crystal scripts | |
def chrono(text) | |
s=Time.now | |
yield | |
e=Time.now | |
d=(e.to_f-s.to_f)*1000 | |
if d>1 | |
puts "#{text} : #{d} ms" | |
else | |
puts "#{text} : #{d*1000} micro s" | |
end | |
end | |
class Array | |
def *(c0: Int) | |
l=self.clone | |
return l if c0<=0 | |
c=c0-1 | |
while c>0 | |
if l.size>self.size && c>=(l.size/self.size) | |
c=c-(l.size/self.size) | |
l = l + l.clone | |
else | |
l = l + self.clone | |
c-=1 | |
end | |
end | |
l | |
end | |
end | |
##################### insertion sort | |
def isort(a) | |
1.upto(a.length - 1) do |i| | |
value = a[i] | |
j = i - 1 | |
while j >= 0 && a[j] > value | |
a[j+1] = a[j] | |
j -= 1 | |
end | |
a[j+1] = value | |
end | |
a | |
end | |
########################### quick sort | |
def qsort(a) | |
return [0].clear unless a | |
return isort(a) if a.size<12 | |
pivot=a[a.size/2] | |
h=a.group_by {|e| e<pivot ? 1 : 2 } | |
return qsort(h[1]) + qsort(h[2]) if h.size==2 | |
([a.size/10,10].max).times { | |
pivot=h.values.first[rand(h.values.first.size/2)] | |
h=a.group_by {|e| e<pivot ? 1 : 2 } | |
#puts "." | |
return qsort(h[1]) + qsort(h[2]) if h.size==2 | |
#p [pivot,h] | |
} | |
# puts "alert: qsort #{a.size}" | |
isort(a) | |
end | |
############################## Count sort | |
def csort(a,min=-1,max=-1) | |
min,max=a.minmax unless min>=0 | |
if (max-min)<1000_002 && a.size<(max-min)*10 | |
s=Array.new((max-min+1),0) | |
a.each {|e| s[e-min]+=1 } | |
res=[0].clear | |
s.each_with_index {|e,i| e.times { res << (min+i)} } | |
res | |
else | |
qsort(a) # data too big, csort can't e done | |
end | |
end | |
############################# quick sort terminated by count sort | |
def qcsort(a,min=-1,max=-1) | |
return [0].clear unless a | |
return isort(a) if a.size<8 | |
min,max=a.minmax unless min>=0 | |
return csort(a,min,max) if (max-min)<10_000 && (max-min)<(a.size*10) | |
pivot=a[a.size/2] | |
h=a.group_by {|e| e<pivot ? 1 : 2 } | |
return qcsort(h[1],min,h[1].max) + qcsort(h[2],pivot,max) if h.size==2 | |
([a.size/10,10].max).times { | |
pivot=h.values.first[rand(h.values.first.size/2)] | |
h=a.group_by {|e| e<pivot ? 1 : 2 } | |
#puts "." | |
return qcsort(h[1],min,h[1].max) + qcsort(h[2],pivot,max) if h.size==2 | |
#p [pivot,h] | |
} | |
# puts "alert: qsort #{a.size}" | |
isort(a) | |
end | |
########################### double pivot sort | |
def dsort(a) | |
return [0].clear unless a | |
return a if a.size==0 | |
return isort(a) if a.size<24 | |
(0..3).to_a.each do |i| | |
p1,p2=a[a.size/3-i],a[a.size-a.size/3+i] | |
p1,p2=p2,p1 if p1>p2 | |
next if p1==p2 | |
h1=[0].clear | |
h2=[0].clear | |
h3=[0].clear | |
a.each {|e| | |
if e<p1 | |
h1 << e | |
elsif e>=p1 && e<p2 | |
h2 << e | |
else | |
h3 << e | |
end } | |
return dsort(h1)+dsort(h2)+dsort(h3) | |
end | |
qsort(a) | |
end | |
######################### doubls pivot sort terminated by count sort | |
def dcsort(a,min=-1,max=-1) | |
return [0].clear unless a | |
return isort(a) if a.size<24 | |
min,max=a.minmax unless min>=0 | |
return csort(a,min,max) if (max-min)<10_000 && (max-min)<(a.size*10) | |
(0..3).to_a.each do |i| | |
p1,p2=a[a.size/3-i],a[a.size-a.size/3+i] | |
p1,p2=p2,p1 if p1>p2 | |
next if p1==p2 | |
h1=[0].clear | |
h2=[0].clear | |
h3=[0].clear | |
a.each {|e| | |
if e<p1 | |
h1 << e | |
elsif e>=p1 && e<p2 | |
h2 << e | |
else | |
h3 << e | |
end } | |
return dcsort(h1,min,h1.size>0 ? h1.max : min)+dcsort(h2,p1,p2)+dcsort(h3,p2,max) | |
end | |
qcsort(a) | |
end | |
################################################################## | |
# T e s t a n d m e a s u r e s | |
################################################################## | |
[ | |
(1..1000).map {|a| a/4 }, | |
(1..10000).to_a.reverse, | |
(1..10000).to_a.shuffle, | |
[2]*100, | |
(0..20_000).map {|a| a*a} + (0..20_000).map {|a| a*a} , | |
(1000..10000).to_a+(1..1000-1).to_a.shuffle, | |
(1000..100000).to_a+(1..1000-1).to_a.shuffle, | |
(0..20_000).map {|a| a*a}.shuffle , | |
(0..1000_000).to_a.shuffle, | |
(0..3_000_000).to_a.shuffle, | |
].each {|a| | |
ref = a.dup.sort | |
puts "===== %s.. len=%d" % [a.first(10).join(", "),a.size] | |
Benchmark.ips do |x| | |
x.report("native") { p "error" unless a.dup.sort()==ref } | |
x.report(" qsort") { p "error" unless qsort(a.dup)==ref } | |
x.report(" dsort") { p "error" unless dsort(a.dup)==ref } | |
x.report("qcsort") { p "error" unless qcsort(a.dup)==ref } | |
x.report("dcsort") { p "error" unless dcsort(a.dup)==ref } | |
x.report(" csort") { p "error" unless csort(a.dup)==ref } | |
end | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Results: