include "$/inc/console.inc"
macro swap(a,b) {c=a : a=b : b=c}
sub QuickSort(int SortArray[], int Lower, Upper)
'QuickSort iterative (rather than recursive) by Cornel Huth
type stacktype 'for QuickSort
int low
int hi
end type
stacktype lstack[128] 'our stack
int sp 'our stack pointer
int low, hi, i, j, midx, compare
sp = 1
lstack[sp].low = Lower
lstack[sp].hi = Upper
sp += 1
while sp <> 1
sp -= 1
low = lstack[sp].low
hi = lstack[sp].hi
while low < hi
i = low : j = hi
midx = (low + hi) \ 2
compare = SortArray[midx]
while i < j
while SortArray[i] < compare
i += 1
wend
while SortArray[j] > compare
j -= 1
wend
if i <= j then
swap SortArray[i], SortArray(j)
i += 1
j -= 1
end if
wend
if (j - low) < (hi - i) then
if i < hi then
lstack[sp].low = i
lstack[sp].hi = hi
sp += 1
end if
hi = j
else
if low < j then
lstack[sp].low = low
lstack[sp].hi = j
sp += 1
end if
low = i
end if
wend
wend
end sub
int array[] = {4,65,2,-31,0,99,2,83,782,1}
for x=1 to countof array
print array[x] ","
next
printl
quicksort (array[], 1, countof array[])
for x=1 to countof array[]
print array[x] ","
next
printl
printl "Enter ... " : waitkey
Output:include "$/inc/console.inc"
macro swap(a,b, c) {typeof a c : c=a : a=b : b=c}
macro print_array(a, i)
scope
indexbase 1
int i
for i=1 to countof a
print a[i] " "
next
printl
end scope
end macro
type stacktype 'for QuickSort
int low
int hi
end type
macro quick_sort(a, Lower, Upper, lstack, sp, low, hi, compare, midx)
'QuickSort iterative (rather than recursive) by Cornel Huth
scope
indexbase 1
int Lower=1
int Upper=countof a
typeof a compare 'int, double, string etc.
stacktype lstack[128] 'our stack
int sp = 1 'our stack pointer
lstack[sp].low = Lower
lstack[sp].hi = Upper
sp += 1
int low, hi, midx
int i,j
while sp <> 1
sp -= 1
low = lstack[sp].low
hi = lstack[sp].hi
while low < hi
i = low : j = hi
midx = (low + hi) \ 2
compare = a[midx]
while i < j
while a[i] < compare
i += 1
wend
while a[j] > compare
j -= 1
wend
if i <= j then
swap a[i], a[j]
i += 1
j -= 1
end if
wend
if (j - low) < (hi - i) then
if i < hi then
lstack[sp].low = i
lstack[sp].hi = hi
sp += 1
end if
hi = j
else
if low < j then
lstack[sp].low = low
lstack[sp].hi = j
sp += 1
end if
low = i
end if
wend
wend
end scope
end macro
==========================================
int array1[] = {4,65,2,-31,0,99,2,83,782,1}
double array2[] = {4.5,65.5,2,-31.5,0,99,2.5,83,782.5,1}
string array3[] = {lcase("Oxygen"),"is","a","nice","and","powerful","programming","language"}
print_array(array1)
quick_sort(array1)
print_array(array1)
printl
print_array(array2)
quick_sort(array2)
print_array(array2)
printl
print_array(array3)
quick_sort(array3)
print_array(array3)
printl
printl "Enter ..." : waitkey
Output:include "$/inc/console.inc"
macro swap(a,b) {tmpval=a : a=b : b=tmpval}
macro print_array(a,c)
typeof a *arr
@arr = @a
for x=1 to c
print arr[x] " "
next
printl
end macro
'applying indexbase 1
sub bubble_sort(int a[],int c, d) 'd=1 ascending, else descending
u=1 'unsorted
while u
u=false
for i=1 to c-1
if d=1 then 'ascending
if a[i]>a[i+1] then
swap a[i],a[i+1] : u=true
end if
else 'descending
if a[i]<a[i+1] then
swap a[i],a[i+1] : u=true
end if
end if
next
wend
end sub
'applying indexbase 1
sub bubble_sort(double a[],int c, d) 'd=1 ascending, else descending
u=1 'unsorted
while u
u=false
for i=1 to c-1
if d=1 then 'ascending
if a[i]>a[i+1] then
swap a[i],a[i+1] : u=true
end if
else 'descending
if a[i]<a[i+1] then
swap a[i],a[i+1] : u=true
end if
end if
next
wend
end sub
'applying indexbase 1
sub bubble_sort(string a[],int c, d) 'd=1 ascending, else descending
u=1 'unsorted
while u
u=false
for i=1 to c-1
if d=1 then 'ascending
if a[i]>a[i+1] then
swap a[i],a[i+1] : u=true
end if
else 'descending
if a[i]<a[i+1] then
swap a[i],a[i+1] : u=true
end if
end if
next
wend
end sub
==========================================
int array1[] = {4,65,2,-31,0,99,2,83,782,1}
double array2[] = {4.3,65.7,2,-31.4,0,99,2.1,83,782,1}
string array3[] = {lcase("Oxygen"),"is","a","nice","and","powerful","programming","language"}
print_array(array1[], countof array1[])
bubble_sort(array1[], countof array1[], 0)
print_array(array1[], countof array1[],)
bubble_sort(array1[], countof array1[], 1)
print_array(array1[], countof array1[],)
printl
print_array(array2[], countof array2[])
bubble_sort(array2[], countof array2[], 0)
print_array(array2[], countof array2[])
bubble_sort(array2[], countof array2[], 1)
print_array(array2[], countof array2[])
printl
print_array(array3[], countof array3[])
bubble_sort(array3[], countof array3[], 0)
print_array(array3[], countof array3[])
bubble_sort(array3[], countof array3[], 1)
print_array(array3[], countof array3[])
printl
printl "Enter ..." : waitkey
Output:include "$/inc/console.inc"
macro swap(a,b) {tmpval=a : a=b : b=tmpval}
macro print_array(a,c)
typeof a *arr
@arr = @a
for x=1 to c
print arr[x] " "
next
printl
end macro
'applying indexbase 1
macro bubble_sort(a,c,d) 'd=1 ascending, else descending
typeof a *bsa
@bsa = @a
u=1 'unsorted
while u
u=false
for i=1 to c-1
if d=1 then 'ascending
if bsa[i]>bsa[i+1] then
swap bsa[i],bsa[i+1] : u=true
end if
else 'descending
if bsa[i]<bsa[i+1] then
swap bsa[i],bsa[i+1] : u=true
end if
end if
next
wend
end macro
==========================================
int array1[] = {4,65,2,-31,0,99,2,83,782,1}
double array2[] = {4.3,65.7,2,-31.4,0,99,2.1,83,782,1}
string array3[] = {lcase("Oxygen"),"is","a","nice","and","powerful","programming","language"}
print_array(array1[], countof array1[])
bubble_sort(array1[], countof array1[], 0)
print_array(array1[], countof array1[],)
bubble_sort(array1[], countof array1[], 1)
print_array(array1[], countof array1[],)
printl
print_array(array2[], countof array2[])
bubble_sort(array2[], countof array2[], 0)
print_array(array2[], countof array2[])
bubble_sort(array2[], countof array2[], 1)
print_array(array2[], countof array2[])
printl
print_array(array3[], countof array3[])
bubble_sort(array3[], countof array3[], 0)
print_array(array3[], countof array3[])
bubble_sort(array3[], countof array3[], 1)
print_array(array3[], countof array3[])
printl
printl "Enter ..." : waitkey
Output:'2017-09-07 T 12:48:05
'POLYMORPHIC BUBBLE SORT USING MACROS
include console
macro swap(a,b, c)
typeof a c
c=a
a=b
b=c
end macro
macro bubble_sort(a,d, cc,u,i) 'd=1 ascending, else descending
scope
indexbase 1
int cc=countof(a)-1
int u=1 'unsorted
int i
while u
u=false
for i=1 to cc
if d=1 then 'ascending
if a[i]>a[i+1] then
swap a[i],a[i+1] : u=true
end if
else 'descending
if a[i]<a[i+1] then
swap a[i],a[i+1] : u=true
end if
end if
next
cc-- 'FINAL ELEMENT IS FIXED
wend
end scope
end macro
macro list(a, i)
scope
indexbase 1
int i
for i=1 to countof a
print a[i] " "
next
print chr(13,10)
end scope
end macro
int a[]={1.25,2,3,4,5,6,7,8,9,10,"ten"}
bubble_sort(a,0)
print "int: " : list a
float a[]={1.25,2,3,4,5,6,7,8,9,10,"ten"}
bubble_sort(a,0)
print "double: " : list a
string a[]={1.25,2,3,4,5,6,7,8,9,10,"ten"}
bubble_sort(a,0)
print "string: " : list a
waitkey
include "$/inc/console.inc"
macro swap(a,b, c)
typeof a c
c=a
a=b
b=c
end macro
macro print_array(a, i)
scope
indexbase 1
int i
for i=1 to countof a
print a[i] " "
next
printl
end scope
end macro
'applying indexbase 1
macro bubble_sort(a,d, cc,u,i) 'd=1 ascending, else descending
scope
indexbase 1
int cc=countof(a)-1
int u=1 'unsorted
int i
while u
u=false
for i=1 to cc
if d=1 then 'ascending
if a[i]>a[i+1] then
swap a[i],a[i+1] : u=true
end if
else 'descending
if a[i]<a[i+1] then
swap a[i],a[i+1] : u=true
end if
end if
next
cc-- 'FINAL ELEMENT IS FIXED
wend
end scope
end macro
==========================================
int array1[] = {4,65,2,-31,0,99,2,83,782,1}
double array2[] = {4.5,65.5,2,-31.5,0,99,2.5,83,782.5,1}
string array3[] = {lcase("Oxygen"),"is","a","nice","and","powerful","programming","language"}
print_array(array1)
bubble_sort(array1, 0)
print_array(array1)
bubble_sort(array1, 1)
print_array(array1)
printl
print_array(array2)
bubble_sort(array2, 0)
print_array(array2)
bubble_sort(array2, 1)
print_array(array2)
printl
print_array(array3)
bubble_sort(array3, 0)
print_array(array3)
bubble_sort(array3, 1)
print_array(array3)
printl
printl "Enter ..." : waitkey
'bottom-up merge-sort procedure
===============================
macro mergeSort(
idx,ct,cp, 'params
src,dest,setsz,cmpr,sw,j,k,kk,bi,bj,ej,ni,nj 'encapsulated
)
scope
indexbase 1
'
' idx index array must have ct*2 elements
' ct element count
' cp comparator callback/macro
'
sys src ' index offset for elements to be compared
sys dest ' index offset for merged ordered elements
sys setsz ' merge group size
sys cmpr ' flag to invoke comparator
sys sw ' flag to select from second group instead of first
sys j ' general indexer
sys k ' general indexer
sys kk ' element counter
sys bi ' base index for first group
sys bj ' base index for second group
sys ej ' boundary index for second goup
sys ni ' position for first compare element
sys nj ' position for second compare element
src=0
dest=ct
setsz=1
do 'MERGING LOOP
if setsz>=ct then
if src>0 then 'COPY INDEX VALUES BACK TO BASE
copy @idx, ct*sizeof(sys)+@idx, ct*sizeof(sys)
end if
exit do 'DONE
end if
kk=1
bi=src+1 : ni=bi
bj=bi+setsz : nj=bj
ej=bj+setsz
k=src+ct+1
if ej>k then ej=k
setsz+=setsz 'SET STRIDE FOR EACH MERGE 2 4 8 ...
do 'A MERGING PASS
if kk>ct then exit do 'ALL ELEMENTS PROCESSED
if ni>=bj then
if nj>=ej then
'MOVE TO NEXT GROUP
bi+=setsz : ni=bi
bj+=setsz : nj=bj
ej+=setsz
k=src+ct+1 'DATA BOUNDARY
if ej>k then ej=k 'CLIP BOUNDARY
cmpr=1 : sw=0 'COMPARE BEFORE PICKING
else
cmpr=0 : sw=1 'ONLY PICK FROM SECOND GROUP
end if
elseif nj>=ej then
cmpr=0 : sw=0 'ONLY PICK FROM FIRST GROUP
else
cmpr=1 : sw=0 'COMPARE BEFORE PICKING
end if
if cmpr
cp( sw, idx[ni], idx[nj] ) 'DO COMPARE
end if
if sw then 'PICK FROM SECOND GROUP
j=idx[nj] : nj++
else 'PICK FROM FIRST GROUP
j=idx[ni] : ni++
end if
k=dest+kk : idx[k]=j 'ASSIGN VALUE TO DESTINATION LOCATION
kk++ 'INCR ELEMENT COUNT
end do
swap src,dest 'SWAP SOURCE/DESTINATION INDEX BUFFER BASES
end do
end scope
end macro
'bottom-up merge-sort procedure
===============================
macro mergeSortP(
idx,ct,cp, 'params
src,dest,setsz,cmpr,sw,kk,bi,bj,ej,ed,ni,nj,sx,dj,sd 'encapsulated
)
'
' idx index array must have ct*2 elements
' ct element count
' cp comparator callback/macro
'
%= sx sizeof idx 'element size
%= sd ct*sx 'size of index data (bytes)
'
sys src ' index offset for elements to be compared
sys dest ' index offset for merged ordered elements
sys setsz ' merge group size X sizeof idx element
sys cmpr ' flag to invoke comparator
sys sw ' flag to select from second group instead of first
sys kk ' element counter
sys bi ' base for first group
sys bj ' base for second group
sys ej ' boundary for second goup
sys ed ' source data boundary
typeof idx * ni ' position for first compare element
typeof idx * nj ' position for second compare element
typeof idx * dj ' destination for element
src=@idx
dest=sd+@idx
setsz=sx 'INITIAL STRIDE IS SIZE OF IDX ELEMENT
do 'MERGING LOOP
if setsz>=sd then
if src<>@idx then 'COPY INDEX VALUES BACK TO BASE
copy @idx, @idx+sd, sd
end if
exit do 'DONE
end if
kk=1
bi=src
bj=bi+setsz : @nj=@bj
ej=bj+setsz
@ni=bi
@nj=bj
ed=src+sd 'DATA BOUNDARY
if ej>ed then ej=ed
@dj=dest
setsz+=setsz 'DOUBLE STRIDE FOR EACH MERGE 8,16,32 ...
do 'NEXT MERGING PASS
if kk>ct then exit do 'ALL ELEMENTS PROCESSED
if @ni>=bj then
if @nj>=ej then
'MOVE TO NEXT GROUP
bi+=setsz : @ni=bi
bj+=setsz : @nj=bj
ej+=setsz
if ej>ed then ej=ed 'CLIP BOUNDARY
cmpr=1 : sw=0 'COMPARE BEFORE PICKING
else
cmpr=0 : sw=1 'ONLY PICK FROM SECOND GROUP
end if
elseif @nj>=ej then
cmpr=0 : sw=0 'ONLY PICK FROM FIRST GROUP
else
cmpr=1 : sw=0 'COMPARE BEFORE PICKING
end if
if cmpr then
cp sw, ni, nj 'COMPARE PROCEDURE
end if
if sw then 'PICK FROM SECOND GROUP
dj=nj : @nj+=sx
else 'PICK FROM FIRST GROUP
dj=ni : @ni+=sx
end if
@dj+=sx 'NEXT DESTINATION
kk++ 'INCR ELEMENT COUNT
end do
swap src,dest 'SWAP SOURCE/DESTINATION IDX BASES
end do
end macro
include generics
include console
'CREATE SOME DATA
string dat={"a2","a1","a","b","c","d","e","f","g","h","i","j"}
%= ct = spanof dat
'CREATE AN INDEX FOR TESTING
int idx[ct*2]
for i=1 to ct : idx[i]=i : next 'prime the index
sub compare(sys *sw,i,j)
if dat[i]<dat[j] then sw=1 'DESCENDING ORDER
end sub
mergeSort idx,ct,compare
//https://stackoverflow.com/questions/1557894/non-recursive-merge-sort
include "$/inc/console.inc"
macro merge_sort(a,d,b,
n,l,r,r_max,m,k,i,j)
indexbase 1
int n=countof a
int r, r_max, m, k
int i,j
'' sys ba=n*2*sizeof string : string b[] at getmemory ba
k=1
while k < n+1
l=1
while (l+k-1) < n+1
r = l + k
r_max = r + k
if (r_max > n+1) then r_max = n+1
m = l : i = l : j = r
while (i < r and j < r_max)
if d=1 then
if (a[i] <= a[j]) then
b[m] = a[i] : i++
else
b[m] = a[j] : j++
end if
else
if (a[i] >= a[j]) then
b[m] = a[i] : i++
else
b[m] = a[j] : j++
end if
end if
m++
wend
while (i < r)
b[m]=a[i] : i++ : m++
wend
while (j < r_max)
b[m]=a[j] : j++ : m++
wend
for m=l to r_max-1
a[m] = b[m]
next
l += k*2
wend
k *= 2
wend
' freememory b
end macro
==========================================
macro print_array(a, i)
scope
indexbase 1
int i
for i=1 to countof a
print a[i] " "
next
printl
end scope
end macro
int array1[] = {30,5,24,11,26,20,4,23,9,25,6,28,15,27,7,22,10,3,1,13,21,29,17,2,19,8,16,14,12,18}
double array2[] = {4.5,65.5,2,-31.5,0,99,2.5,83,782.5,1}
string array3[] = {lcase("Oxygen"),"is","a","nice","and","powerful","programming","language"}
print_array(array1)
sys ba=countof array1 *2*sizeof array1 : int temparray[] at getmemory ba
merge_sort(array1, 0, temparray)
print_array(array1)
merge_sort(array1, 1, temparray)
print_array(array1)
freememory @temparray
printl
print_array(array2)
sys ba=countof array2 *2*sizeof array1 : double temparray[] at getmemory ba
merge_sort(array2, 0, temparray)
print_array(array2)
merge_sort(array2, 1, temparray)
print_array(array2)
freememory @temparray
printl
print_array(array3)
sys ba=countof array3 *2*sizeof array3 : string temparray[] at getmemory ba
merge_sort(array3, 0, temparray)
print_array(array3)
merge_sort(array3, 1, temparray)
print_array(array3)
freememory @temparray
printl
==========================================
'Use Windows functions
! GetTickCount lib "kernel32.dll" () as sys
! rand lib "msvcrt.dll" cdecl () as int
! srand lib "msvcrt.dll" cdecl (int seed)
int array4[1000000]
'double array4[1000000]
srand(GetTickCount) 'Randomize
for x=1 to 100 : array4[x]=rand()/2.5 : next
'print_array(array4)
printl "Sorting " countof array4 " items of type: " typeof array4 " in ascending order with MergeSort:" cr
t1=GetTickCount()
sys ba=countof array4 *2*sizeof array4 : int temparray[] at getmemory ba
'sys ba=countof array4 *2*sizeof array4 : double temparray[] at getmemory ba
merge_sort(array4, 1, temparray)
freememory @temparray
t2=GetTickCount()
'print_array(array4)
printl "Elapsed Time: " (t2-t1)/1000
printl
printl "Now sorting the sorted array in descending order with MergeSort:" cr
t1=GetTickCount()
sys ba=countof array4 *2*sizeof array4 : int temparray[] at getmemory ba
'sys ba=countof array4 *2*sizeof array4 : double temparray[] at getmemory ba
merge_sort(array4, 0, temparray)
freememory @temparray
t2=GetTickCount()
'print_array(array4)
printl "Elapsed Time: " (t2-t1)/1000
printl
printl "Enter ..." : waitkey
'2017-09-11 T 12:13:35
'FILTERING AND SORTING
include generics
include console
'CREATE SOME DATA
string dat={"a2","a1","a","b","c","d","e","f","g","h","i","j"}
int ct = spanof dat
int cf
macro filter(f,i)
if asc(dat[i])<=0x65 then f=1 'e'
end macro
macro compare(sw,i,j)
if dat[i]<dat[j] then sw=1 'DESCENDING ORDER
end macro
newSortIndex idx,ct,cf,filter,compare
'SHOW RESULTS
print "DATA" cr
listArray dat,print,ct
print "INDEXED DATA" cr
listArray dat,print,cf,idx
print "INDEX" cr
listArray idx,print,cf
waitkey
delIndex idx