September 2017 Update

This commit is contained in:
Ingy döt Net 2017-09-23 10:01:46 +02:00
parent bba7bfd280
commit ba8067c3b7
14570 changed files with 153136 additions and 63871 deletions

View file

@ -0,0 +1,368 @@
--
-- demo\rosetta\Compare_sorting_algorithms.exw
--
constant XQS = 01 -- (set to 1 to exclude quick_sort and shell_sort from ones)
include pGUI.e
Ihandle dlg, tabs, plot
Ihandles plots
function quick_sort2(sequence x)
integer n = length(x), c, mid, midn
object xi, midval
sequence left = {}, right = {}
if n<2 then
return x -- already sorted (trivial case)
end if
mid = floor((n+1)/2)
midval = x[mid]
x[mid] = x[1]
midn = 1
for i=2 to n do
xi = x[i]
c = compare(xi,midval)
if c<0 then
left &= xi
elsif c>0 then
right &= xi
else
midn += 1
end if
end for
return quick_sort2(left) & repeat(midval,midn) & quick_sort2(right)
end function
function quick_sort(sequence s)
sequence qstack
integer first, last, stackptr, I, J, tmp, pivot
qstack = repeat(0,floor((length(s)/5)+10)) -- create a stack
first = 1
last = length(s)
stackptr = 0
while 1 do
while first<last do
pivot = s[floor(last+first)/2]
I = first
J = last
while 1 do
while s[I]<pivot do
I += 1
end while
while s[J]>pivot do
J -= 1
end while
if I>J then exit end if
if I<J then
tmp = s[I]
s[I] = s[J]
s[J] = tmp
end if
I += 1
J -= 1
if I>J then exit end if
end while
if I<last then
qstack[stackptr+1] = I
qstack[stackptr+2] = last
stackptr += 2
end if
last = J
end while
if stackptr=0 then exit end if
stackptr -= 2
first = qstack[stackptr+1]
last = qstack[stackptr+2]
end while
return s
end function
function radixSortn(sequence s, integer n)
sequence buckets = repeat({},10)
sequence res = {}
for i=1 to length(s) do
integer digit = remainder(floor(s[i]/power(10,n-1)),10)+1
buckets[digit] = append(buckets[digit],s[i])
end for
for i=1 to length(buckets) do
integer len = length(buckets[i])
if len!=0 then
if len=1 or n=1 then
res &= buckets[i]
else
res &= radixSortn(buckets[i],n-1)
end if
end if
end for
return res
end function
function split_by_sign(sequence s)
sequence buckets = {{},{}}
for i=1 to length(s) do
integer si = s[i]
if si<0 then
buckets[1] = append(buckets[1],-si)
else
buckets[2] = append(buckets[2],si)
end if
end for
return buckets
end function
function radix_sort(sequence s)
integer mins = min(s)
integer passes = max(max(s),abs(mins))
passes = floor(log10(passes))+1
if mins<0 then
sequence buckets = split_by_sign(s)
buckets[1] = reverse(sq_uminus(radixSortn(buckets[1],passes)))
buckets[2] = radixSortn(buckets[2],passes)
s = buckets[1]&buckets[2]
else
s = radixSortn(s,passes)
end if
return s
end function
function shell_sort(sequence s)
integer gap = floor(length(s)/2), j
object temp
while gap>0 do
for i=gap to length(s) do
temp = s[i]
j = i-gap
while j>=1 and temp<=s[j] do
s[j+gap] = s[j]
j -= gap
end while
s[j+gap] = temp
end for
gap = floor(gap/2)
end while
return s
end function
function shell_sort2(sequence x)
integer gap, j, first, last
object xi, xj
last = length(x)
gap = floor(last/10)+1
while TRUE do
first = gap+1
for i=first to last do
xi = x[i]
j = i-gap
while TRUE do
xj = x[j]
if xi>=xj then
j += gap
exit
end if
x[j+gap] = xj
if j<=gap then
exit
end if
j -= gap
end while
x[j] = xi
end for
if gap=1 then
return x
else
gap = floor(gap/3.5)+1
end if
end while
end function
function siftDown(sequence arr, integer s, integer last)
integer root = s
while root*2<=last do
integer child = root*2
if child<last and arr[child]<arr[child+1] then
child += 1
end if
if arr[root]>=arr[child] then exit end if
object tmp = arr[root]
arr[root] = arr[child]
arr[child] = tmp
root = child
end while
return arr
end function
function heapify(sequence arr, integer count)
integer s = floor(count/2)
while s>0 do
arr = siftDown(arr,s,count)
s -= 1
end while
return arr
end function
function heap_sort(sequence arr)
integer last = length(arr)
arr = heapify(arr,last)
while last>1 do
object tmp = arr[1]
arr[1] = arr[last]
arr[last] = tmp
last -= 1
arr = siftDown(arr,1,last)
end while
return arr
end function
include builtins/sort.e
enum ONES = 1, SORTED = 2, RANDOM = 3, REVERSE = 4
constant tabtitles = {"ones","sorted","random","reverse"}
integer tabidx = 3
integer STEP
function tr(sequence name, integer rid=routine_id(name))
return {name,rid}
end function
constant tests = {tr("quick_sort"),
tr("quick_sort2"),
tr("radix_sort"),
tr("shell_sort"),
tr("shell_sort2"),
tr("heap_sort"),
tr("sort"), -- builtin
}
sequence results = repeat(repeat({}, length(tests)),length(tabtitles))
sequence dsdx = repeat(repeat(0,length(tests)),length(tabtitles))
integer ds_index
function idle_action_cb()
atom best = -1, -- fastest last
besti = 0, -- 1..length(tests)
bestt = 0, -- 1..length(tabtitles)
len
sequence todo
--
-- Search for something to do, active/visible tab first.
-- Any result set of length 0 -> just do one.
-- Of all result sets<8, pick the lowest [$].
--
todo = {tabidx}
for t=1 to length(tabtitles) do
if t!=tabidx then todo &= t end if
end for
for t=1 to length(tabtitles) do
integer ti = todo[t]
for i=1 to length(results[ti]) do
len = length(results[ti][i])
if len=0 then
best = 0
besti = i
bestt = ti
exit
elsif len<8 then
if (best=-1) or (best>results[ti][i][$]) then
best = results[ti][i][$]
besti = i
bestt = ti
end if
end if
end for
if (t=1) and (besti!=0) then exit end if
end for
if best>10 then
-- cop out if it is getting too slow
besti = 0
end if
if besti!=0 then
STEP = iff(not XQS and bestt=ONES?1000:100000)
len = (length(results[bestt][besti])+1)*STEP
sequence test = iff(bestt=ONES?repeat(1,len):
iff(bestt=SORTED?tagset(len):
iff(bestt=RANDOM?shuffle(tagset(len)):
iff(bestt=REVERSE?reverse(tagset(len)):9/0))))
ds_index = dsdx[bestt][besti]
atom t0 = time()
sequence check = call_func(tests[besti][2],{test})
t0 = time()-t0
-- if check!=sort(test) then ?9/0 end if
plot = plots[bestt]
IupPlotInsert(plot, ds_index, -1, len, t0)
results[bestt][besti] = append(results[bestt][besti],t0)
IupSetAttribute(plot,"REDRAW",NULL)
sequence progress = {bestt}
for i=1 to length(results[bestt]) do
progress &= length(results[bestt][i])
end for
IupSetStrAttribute(dlg,"TITLE","Compare sorting algorithms %s",{sprint(progress)})
return IUP_CONTINUE
end if
IupSetAttribute(dlg,"TITLE","Compare sorting algorithms (all done, idle)")
return IUP_IGNORE -- all done, remove callback
end function
constant cb_idle_action = Icallback("idle_action_cb")
function tabchange_cb(Ihandle /*self*/, Ihandle /*new_tab*/)
tabidx = IupGetInt(tabs,"VALUEPOS")+1
plot = plots[tabidx]
return IUP_DEFAULT;
end function
function esc_close(Ihandle /*ih*/, atom c)
if c=K_ESC then return IUP_CLOSE end if
return IUP_CONTINUE
end function
procedure main()
IupOpen()
plots = {}
for i=1 to length(tabtitles) do
if XQS then
-- results[ONES][1] = repeat(0,8)
results[ONES][4] = repeat(0,8)
end if
plot = IupPlot()
IupSetAttribute(plot,"MENUITEMPROPERTIES","YES")
IupSetAttribute(plot,"TABTITLE",tabtitles[i])
IupSetAttribute(plot,"GRID","YES")
IupSetAttribute(plot,"MARGINLEFT","50")
IupSetAttribute(plot,"MARGINBOTTOM","40")
IupSetAttribute(plot,"LEGEND","YES")
IupSetAttribute(plot,"LEGENDPOS","TOPLEFT")
-- IupSetAttribute(plot,"AXS_YSCALE","LOG10")
-- IupSetAttribute(plot,"AXS_XSCALE","LOG10")
for j=1 to length(tests) do
IupPlotBegin(plot)
dsdx[i][j] = IupPlotEnd(plot)
IupSetAttribute(plot,"DS_NAME",tests[j][1])
end for
plots = append(plots,plot)
end for
tabs = IupTabs(plots)
IupSetCallback(tabs, "TABCHANGE_CB", Icallback("tabchange_cb"))
dlg = IupDialog(tabs)
IupSetAttributes(dlg, "RASTERSIZE=%dx%d", {640, 480})
IupSetAttribute(dlg, "TITLE", "Compare sorting algorithms")
IupSetCallback(dlg, "K_ANY", Icallback("esc_close"))
IupShow(dlg)
IupSetInt(tabs, "VALUEPOS", tabidx-1)
IupSetGlobalFunction("IDLE_ACTION", cb_idle_action)
IupMainLoop()
IupClose()
end procedure
main()