Last active
January 6, 2021 05:20
-
-
Save thehans/ac6770127291416425d74f771ed073b0 to your computer and use it in GitHub Desktop.
OpenSCAD radix sort implementation
This file contains 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
// LSD Radix sort (stable) | |
// base: should be a power of two, otherwise exit condition (d==m) might not be reached. | |
// key: 3 possible types | |
// - number (vector index into each element) | |
// - function (takes element and returns the key value) | |
// - undef (elements are used directly as the key) | |
// key values need not be integers, but will be treated as integers via floor() | |
// e.g. [1.5, 1, 1.2] is considered sorted since they are all same key after floor | |
function radix_sort(v,base=4,key) = key==undef ? | |
_rs(v,1,pow(base,-floor(log(max(v))/log(base))),base) : | |
is_num(key) ? | |
_rski(v,1,pow(base,-floor(log(max([for(x=v) v[key]]))/log(base))),base,key) : | |
is_function(key) ? | |
_rskf(v,1,pow(base,-floor(log(max([for(x=v) key(x)]))/log(base))),base,key) : | |
assert(false, "\"key\" argument must be either undef, number (index), or function"); | |
// v: vector to stable sort | |
// d: inverse of the current digit | |
// m: inverse of the max digit | |
// r: radix (base) | |
// k: key(index or function) | |
function _rs(v,d,m,r) = let( // element == key | |
kvps = [for(x=v) [floor(x*d)%r,x]], | |
v = [for(i=[0:1:r-1],x=kvps) if(x[0]==i) x[1]] | |
) d==m ? v : _rs(v,d/r,m,r); | |
function _rski(v,d,m,r,k) = let( // indexed key | |
kvps = [for(x=v) [floor(x[k]*d)%r,x]], | |
v = [for(i=[0:1:r-1],x=kvps) if(x[0]==i) x[1]] | |
) d==m ? v : _rski(v,d/r,m,r,k); | |
function _rskf(v,d,m,r,k) = let( // function returns key | |
kvps = [for(x=v) [floor(k(x)*d)%r,x]], | |
v = [for(i=[0:1:r-1],x=kvps) if(x[0]==i) x[1]] | |
) d==m ? v : _rskf(v,d/r,m,r,k); | |
seed = 0; | |
v = [for(x=rands(0,pow(2,32),1e5,seed)) floor(x)]; | |
sorted = radix_sort(v,base=4); | |
// function-literal key can be used to scale float values for more accurate sorting | |
//v = rands(0,pow(2,16),1e5,seed); | |
//sorted = radix_sort(v, key=function(x)x*65536); | |
echo(len(v)); | |
echo(len(sorted)); | |
//echo(sorted); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment