mirror of
https://github.com/BelfrySCAD/BOSL2.git
synced 2024-12-29 16:29:40 +00:00
Sort debugging and optimizing
There were bugs in the previous sorting functions. They didn't check the homogeneity of the input list before calling _sort_scalars and _sort_vectors. The bug might result in wrong order and missing list elements in the output. Besides correcting the bug a recode of all sorting functions result in better performance and a enlargement of their scope. With the new functions, list of vectors of any dimension may be sorted, even with idx given, with the native comparison operators. The scope of indexed sorting is also extended. The file test_arrays has been extended to check the new funcionality. New functions: is_homogeneous - checks if a list has elements of the same type (although not distinguing booleans from numbers) up to a given depth _sort_vectors - internal function to sort homgeneous lists of vectors using native comparison operators; extends the scope of the previous _sort_vectors# functions with better performance _lexical_sort - internal function to sort non-homogeneous lists; uses compare_vals _indexed_sort - internal function to perform indexed sorting of non-homogeneous lists; uses compar_vals Changed/reviewed functions: _valid_idx - doesn't requires the input of imin and imax args sort - explores the internal functions to get better performance and an enlarged scope sortidx - explores the internal functions to get better performance and an enlarged scope _sort_general - just for sortings of non-homogeneous lists using compare_vals _array_dim_recurse - changed for bit better performance Functions eliminated: _sort_vectors1 _sort_vectors2 _sort_vectors3 _sort_vectors4
This commit is contained in:
parent
14b0f264ac
commit
bbe4ad1467
2 changed files with 198 additions and 164 deletions
289
arrays.scad
289
arrays.scad
|
@ -19,6 +19,32 @@
|
|||
// Section: List Query Operations
|
||||
|
||||
|
||||
// Function: is_homogeneous()
|
||||
// Usage:
|
||||
// is_homogeneous(list,depth)
|
||||
// Description:
|
||||
// Returns true when the list have elements of same type up to the depth `depth`.
|
||||
// Booleans and numbers are not distinguinshed as of distinct types.
|
||||
// Arguments:
|
||||
// list - the list to check
|
||||
// depth - the lowest level the check is done
|
||||
// Example:
|
||||
// is_homogeneous( [[1,["a"]], [2,["b"]]] ) // Returns true
|
||||
// is_homogeneous( [[1,["a"]], [2,[true]]] ) // Returns false
|
||||
// is_homogeneous( [[1,["a"]], [2,[true]]], 1 ) // Returns true
|
||||
// is_homogeneous( [[1,["a"]], [2,[true]]], 2 ) // Returns false
|
||||
// is_homogeneous( [[1,["a"]], [true,["b"]]] ) // Returns true
|
||||
function is_homogeneous(l, depth) =
|
||||
!is_list(l) || l==[] ? false :
|
||||
let( l0=l[0] )
|
||||
[] == [for(i=[1:len(l)-1]) if( ! _same_type(l[i],l0, depth+1) ) 0 ];
|
||||
|
||||
function _same_type(a,b, depth) =
|
||||
(depth==0) || (a>=b) || (a==b) || (a<=b)
|
||||
|| ( is_list(a) && is_list(b) && len(a)==len(b)
|
||||
&& []==[for(i=idx(a)) if( ! _same_type(a[i],b[i],depth-1) )0] );
|
||||
|
||||
|
||||
// Function: select()
|
||||
// Description:
|
||||
// Returns a portion of a list, wrapping around past the beginning, if end<start.
|
||||
|
@ -597,6 +623,23 @@ function list_fit(array, length, fill) =
|
|||
|
||||
// Section: List Shuffling and Sorting
|
||||
|
||||
|
||||
// returns true for valid index specifications idx in the interval [imin, imax)
|
||||
// note that idx can't have any value greater or EQUAL to imax
|
||||
// this allows imax=INF as a bound to numerical lists
|
||||
function _valid_idx(idx,imin,imax) =
|
||||
is_undef(idx)
|
||||
|| ( is_finite(idx)
|
||||
&& ( is_undef(imin) || idx>=imin )
|
||||
&& ( is_undef(imax) || idx< imax ) )
|
||||
|| ( is_list(idx)
|
||||
&& ( is_undef(imin) || min(idx)>=imin )
|
||||
&& ( is_undef(imax) || max(idx)< imax ) )
|
||||
|| ( is_range(idx)
|
||||
&& ( is_undef(imin) || (idx[1]>0 && idx[0]>=imin ) || (idx[1]<0 && idx[0]<=imax ) )
|
||||
&& ( is_undef(imax) || (idx[1]>0 && idx[2]<=imax ) || (idx[1]<0 && idx[2]>=imin ) ) );
|
||||
|
||||
|
||||
// Function: shuffle()
|
||||
// Description:
|
||||
// Shuffles the input list into random order.
|
||||
|
@ -611,7 +654,8 @@ function shuffle(list) =
|
|||
concat(shuffle(left), shuffle(right));
|
||||
|
||||
|
||||
// Sort a vector of scalar values
|
||||
// Sort a vector of scalar values with the native comparison operator
|
||||
// all elements should have the same type.
|
||||
function _sort_scalars(arr) =
|
||||
len(arr)<=1 ? arr :
|
||||
let(
|
||||
|
@ -623,100 +667,62 @@ function _sort_scalars(arr) =
|
|||
concat( _sort_scalars(lesser), equal, _sort_scalars(greater) );
|
||||
|
||||
|
||||
// Sort a vector of vectors based on the first entry only of each vector
|
||||
function _sort_vectors1(arr) =
|
||||
len(arr)<=1 ? arr :
|
||||
!(len(arr)>0) ? [] :
|
||||
// lexical sort of a homogeneous list of vectors
|
||||
// uses native comparison operator
|
||||
function _sort_vectors(arr, _i=0) =
|
||||
len(arr)<=1 || _i>=len(arr[0]) ? arr :
|
||||
let(
|
||||
pivot = arr[floor(len(arr)/2)],
|
||||
lesser = [ for (y = arr) if (y[0] < pivot[0]) y ],
|
||||
equal = [ for (y = arr) if (y[0] == pivot[0]) y ],
|
||||
greater = [ for (y = arr) if (y[0] > pivot[0]) y ]
|
||||
pivot = arr[floor(len(arr)/2)][_i],
|
||||
lesser = [ for (entry=arr) if (entry[_i] < pivot ) entry ],
|
||||
equal = [ for (entry=arr) if (entry[_i] == pivot ) entry ],
|
||||
greater = [ for (entry=arr) if (entry[_i] > pivot ) entry ]
|
||||
)
|
||||
concat( _sort_vectors1(lesser), equal, _sort_vectors1(greater) );
|
||||
concat(
|
||||
_sort_vectors(lesser, _i ),
|
||||
_sort_vectors(equal, _i+1 ),
|
||||
_sort_vectors(greater, _i ) );
|
||||
|
||||
|
||||
// Sort a vector of vectors based on the first two entries of each vector
|
||||
// Lexicographic order, remaining entries of vector ignored
|
||||
function _sort_vectors2(arr) =
|
||||
len(arr)<=1 ? arr :
|
||||
!(len(arr)>0) ? [] :
|
||||
// lexical sort of a homogeneous list of vectors by the vector components with indices in idxlist
|
||||
// all idxlist indices should be in the range of the vector dimensions
|
||||
// idxlist must be undef or a simple list of numbers
|
||||
// uses native comparison operator
|
||||
function _sort_vectors(arr, idxlist, _i=0) =
|
||||
len(arr)<=1 || ( is_list(idxlist) && _i>=len(idxlist) ) || _i>=len(arr[0]) ? arr :
|
||||
let(
|
||||
pivot = arr[floor(len(arr)/2)],
|
||||
lesser = [ for (y = arr) if (y[0] < pivot[0] || (y[0]==pivot[0] && y[1]<pivot[1])) y ],
|
||||
equal = [ for (y = arr) if (y[0] == pivot[0] && y[1]==pivot[1]) y ],
|
||||
greater = [ for (y = arr) if (y[0] > pivot[0] || (y[0]==pivot[0] && y[1]>pivot[1])) y ]
|
||||
k = is_list(idxlist) ? idxlist[_i] : _i,
|
||||
pivot = arr[floor(len(arr)/2)][k],
|
||||
lesser = [ for (entry=arr) if (entry[k] < pivot ) entry ],
|
||||
equal = [ for (entry=arr) if (entry[k] == pivot ) entry ],
|
||||
greater = [ for (entry=arr) if (entry[k] > pivot ) entry ]
|
||||
)
|
||||
concat( _sort_vectors2(lesser), equal, _sort_vectors2(greater) );
|
||||
concat(
|
||||
_sort_vectors(lesser, idxlist, _i ),
|
||||
_sort_vectors(equal, idxlist, _i+1),
|
||||
_sort_vectors(greater, idxlist, _i ) );
|
||||
|
||||
|
||||
// Sort a vector of vectors based on the first three entries of each vector
|
||||
// Lexicographic order, remaining entries of vector ignored
|
||||
function _sort_vectors3(arr) =
|
||||
len(arr)<=1 ? arr : let(
|
||||
pivot = arr[floor(len(arr)/2)],
|
||||
lesser = [ for (y = arr)
|
||||
if ( y[0] < pivot[0]
|
||||
|| ( y[0]==pivot[0]
|
||||
&& ( y[1]<pivot[1]
|
||||
|| ( y[1]==pivot[1]
|
||||
&& y[2]<pivot[2] ))))
|
||||
y ],
|
||||
equal = [ for (y = arr)
|
||||
if ( y[0] == pivot[0]
|
||||
&& y[1]== pivot[1]
|
||||
&& y[2]==pivot[2] )
|
||||
y ],
|
||||
greater = [ for (y = arr)
|
||||
if ( y[0] > pivot[0]
|
||||
|| ( y[0]==pivot[0]
|
||||
&& ( y[1] > pivot[1]
|
||||
|| ( y[1]==pivot[1]
|
||||
&& y[2] > pivot[2] ))))
|
||||
y ]
|
||||
) concat( _sort_vectors3(lesser), equal, _sort_vectors3(greater) );
|
||||
|
||||
|
||||
// Sort a vector of vectors based on the first four entries of each vector
|
||||
// Lexicographic order, remaining entries of vector ignored
|
||||
function _sort_vectors4(arr) =
|
||||
len(arr)<=1 ? arr : let(
|
||||
pivot = arr[floor(len(arr)/2)],
|
||||
lesser = [ for (y = arr)
|
||||
if ( y[0] < pivot[0]
|
||||
|| ( y[0]==pivot[0]
|
||||
&& ( y[1]<pivot[1]
|
||||
|| ( y[1]==pivot[1]
|
||||
&& ( y[2]<pivot[2]
|
||||
|| ( y[2]==pivot[2]
|
||||
&& y[3]<pivot[3] ))))))
|
||||
y ],
|
||||
equal = [ for (y = arr)
|
||||
if ( y[0] == pivot[0]
|
||||
&& y[1] == pivot[1]
|
||||
&& y[2] == pivot[2]
|
||||
&& y[3] == pivot[3] )
|
||||
y ],
|
||||
greater = [ for (y = arr)
|
||||
if ( y[0] > pivot[0]
|
||||
|| ( y[0]==pivot[0]
|
||||
&& ( y[1]>pivot[1]
|
||||
|| ( y[1]==pivot[1]
|
||||
&& ( y[2]>pivot[2]
|
||||
|| ( y[2]==pivot[2]
|
||||
&& y[3]>pivot[3] ))))))
|
||||
y ]
|
||||
) concat( _sort_vectors4(lesser), equal, _sort_vectors4(greater) );
|
||||
|
||||
|
||||
// when idx==undef, returns the sorted array
|
||||
// otherwise, returns the indices of the sorted array
|
||||
function _sort_general(arr, idx=undef) =
|
||||
// sorting using compare_vals(); returns indexed list when `indexed==true`
|
||||
function _sort_general(arr, idx=undef, indexed=false) =
|
||||
(len(arr)<=1) ? arr :
|
||||
is_undef(idx)
|
||||
? _sort_scalar(arr)
|
||||
: let( arrind=[for(k=[0:len(arr)-1], ark=[arr[k]]) [ k, [for (i=idx) ark[i]] ] ] )
|
||||
_indexed_sort(arrind);
|
||||
! indexed && is_undef(idx)
|
||||
? _lexical_sort(arr)
|
||||
: let( arrind = _indexed_sort(enumerate(arr,idx)) )
|
||||
indexed
|
||||
? arrind
|
||||
: [for(i=arrind) arr[i]];
|
||||
|
||||
// lexical sort using compare_vals()
|
||||
function _lexical_sort(arr) =
|
||||
arr==[] ? [] : len(arr)==1? arr :
|
||||
let( pivot = arr[floor(len(arr)/2)] )
|
||||
let(
|
||||
lesser = [ for (entry=arr) if (compare_vals(entry, pivot) <0 ) entry ],
|
||||
equal = [ for (entry=arr) if (compare_vals(entry, pivot)==0 ) entry ],
|
||||
greater = [ for (entry=arr) if (compare_vals(entry, pivot) >0 ) entry ]
|
||||
)
|
||||
concat(_lexical_sort(lesser), equal, _lexical_sort(greater));
|
||||
|
||||
|
||||
// given a list of pairs, return the first element of each pair of the list sorted by the second element of the pair
|
||||
// the sorting is done using compare_vals()
|
||||
|
@ -731,52 +737,46 @@ function _indexed_sort(arrind) =
|
|||
concat(_indexed_sort(lesser), equal, _indexed_sort(greater));
|
||||
|
||||
|
||||
// returns true for valid index specifications idx in the interval [imin, imax)
|
||||
// note that idx can't have any value greater or EQUAL to imax
|
||||
function _valid_idx(idx,imin,imax) =
|
||||
is_undef(idx)
|
||||
|| ( is_finite(idx) && idx>=imin && idx< imax )
|
||||
|| ( is_list(idx) && min(idx)>=imin && max(idx)< imax )
|
||||
|| ( valid_range(idx) && idx[0]>=imin && idx[2]< imax );
|
||||
|
||||
|
||||
// Function: sort()
|
||||
// Usage:
|
||||
// sort(list, [idx])
|
||||
// Description:
|
||||
// Sorts the given list using `compare_vals()`, sorting in lexicographic order, with types ordered according to
|
||||
// Sorts the given list in lexicographic order. If the input is a homogeneous simple list or a homogeneous
|
||||
// list of vectors (see function is_homogeneous), the sorting method uses the native comparison operator and is faster.
|
||||
// When sorting non homogeneous list the elements are compared with `compare_vals`, with types ordered according to
|
||||
// `undef < boolean < number < string < list`. Comparison of lists is recursive.
|
||||
// If the list is a list of vectors whose length is from 1 to 4 and the `idx` parameter is not passed, then
|
||||
// `sort` uses a much more efficient method for comparisons and will run much faster. In this case, all entries
|
||||
// in the data are compared using the native comparison operator, so comparisons between types will fail.
|
||||
// When comparing vectors, homogeneous or not, the parameter `idx` may be used to select the components to compare.
|
||||
// Note that homogeneous lists of vectors may contain mixed types provided that for any two list elements
|
||||
// list[i] and list[j] satisfies type(list[i][k])==type(list[j][k]) for all k.
|
||||
// Strings are allowed as any list element and are compared with the native operators although no substring
|
||||
// comparison is possible.
|
||||
// Arguments:
|
||||
// list = The list to sort.
|
||||
// idx = If given, do the comparison based just on the specified index, range or list of indices.
|
||||
// Example:
|
||||
// l = [45,2,16,37,8,3,9,23,89,12,34];
|
||||
// sorted = sort(l); // Returns [2,3,8,9,12,16,23,34,37,45,89]
|
||||
// // Homogeneous lists
|
||||
// l1 = [45,2,16,37,8,3,9,23,89,12,34];
|
||||
// sorted1 = sort(l1); // Returns [2,3,8,9,12,16,23,34,37,45,89]
|
||||
// l2 = [["oat",0], ["cat",1], ["bat",3], ["bat",2], ["fat",3]];
|
||||
// sorted2 = sort(l2); // Returns: [["bat",2],["bat",3],["cat",1],["fat",3],["oat",0]]
|
||||
// // Non-homegenous list
|
||||
// l3 = [[4,0],[7],[3,9],20,[4],[3,1],[8]];
|
||||
// sorted3 = sort(l3); // Returns: [20,[3,1],[3,9],[4],[4,0],[7],[8]]
|
||||
function sort(list, idx=undef) =
|
||||
!is_list(list) || len(list)<=1 ? list :
|
||||
is_def(idx)
|
||||
? assert( _valid_idx(idx,0,len(list)) , "Invalid indices.")
|
||||
let( sarr = _sort_general(list,idx) )
|
||||
[for(i=[0:len(sarr)-1]) list[sarr[i]] ]
|
||||
: let(size = array_dim(list))
|
||||
len(size)==1 ? _sort_scalars(list) :
|
||||
len(size)==2 && size[1] <=4
|
||||
? (
|
||||
size[1]==0 ? list :
|
||||
size[1]==1 ? _sort_vectors1(list) :
|
||||
size[1]==2 ? _sort_vectors2(list) :
|
||||
size[1]==3 ? _sort_vectors3(list)
|
||||
/*size[1]==4*/ : _sort_vectors4(list)
|
||||
)
|
||||
: _sort_general(list);
|
||||
is_homogeneous(list,1)
|
||||
? let(size = array_dim(list[0]))
|
||||
size==0 ? _sort_scalars(list)
|
||||
: len(size)!=1 ? _sort_general(list,idx)
|
||||
: is_undef(idx) ? _sort_vectors(list)
|
||||
: assert( _valid_idx(idx) , "Invalid indices.")
|
||||
_sort_vectors(list,[for(i=idx) i])
|
||||
: _sort_general(list,idx);
|
||||
|
||||
|
||||
// Function: sortidx()
|
||||
// Description:
|
||||
// Given a list, calculates the sort order of the list, and returns
|
||||
// Given a list, sort it as function `sort()`, and returns
|
||||
// a list of indexes into the original list in that sorted order.
|
||||
// If you iterate the returned list in order, and use the list items
|
||||
// to index into the original list, you will be iterating the original
|
||||
|
@ -796,29 +796,26 @@ function sort(list, idx=undef) =
|
|||
// idxs2 = sortidx(lst, idx=0); // Returns: [1,2,0,3]
|
||||
// idxs3 = sortidx(lst, idx=[1,3]); // Returns: [3,0,2,1]
|
||||
function sortidx(list, idx=undef) =
|
||||
assert( is_list(list) || is_string(list) , "Invalid input to sort." )
|
||||
assert( _valid_idx(idx,0,len(list)) , "Invalid indices.")
|
||||
list==[] ? [] :
|
||||
let(
|
||||
size = array_dim(list),
|
||||
aug = is_undef(idx) && (len(size) == 1 || (len(size) == 2 && size[1]<=4))
|
||||
? zip(list, list_range(len(list)))
|
||||
: 0
|
||||
!is_list(list) || len(list)<=1 ? list :
|
||||
is_homogeneous(list,1)
|
||||
? let(
|
||||
size = array_dim(list[0]),
|
||||
aug = ! (size==0 || len(size)==1) ? 0 // for general sorting
|
||||
: [for(i=[0:len(list)-1]) concat(i,list[i])], // for scalar or vector sorting
|
||||
lidx = size==0? [1] : // scalar sorting
|
||||
len(size)==1
|
||||
? is_undef(idx) ? [for(i=[0:len(list[0])-1]) i+1] // vector sorting
|
||||
: [for(i=idx) i+1] // vector sorting
|
||||
: 0 // just to signal
|
||||
)
|
||||
is_undef(idx) && len(size) == 1? subindex(_sort_vectors1(aug),1) :
|
||||
is_undef(idx) && len(size) == 2 && size[1] <=4
|
||||
? (
|
||||
size[1]==0 ? list_range(len(arr)) :
|
||||
size[1]==1 ? subindex(_sort_vectors1(aug),1) :
|
||||
size[1]==2 ? subindex(_sort_vectors2(aug),2) :
|
||||
size[1]==3 ? subindex(_sort_vectors3(aug),3)
|
||||
/*size[1]==4*/ : subindex(_sort_vectors4(aug),4)
|
||||
)
|
||||
: // general case
|
||||
_sort_general(list,idx);
|
||||
|
||||
|
||||
// sort() does not accept strings but sortidx does; isn't inconsistent ?
|
||||
assert( ! ( size==0 && is_def(idx) ),
|
||||
"The specification of `idx` is incompatible with scalar sorting." )
|
||||
assert( _valid_idx(idx) , "Invalid indices." )
|
||||
lidx!=0
|
||||
? let( lsort = _sort_vectors(aug,lidx) )
|
||||
[for(li=lsort) li[0] ]
|
||||
: _sort_general(list,idx,indexed=true)
|
||||
: _sort_general(list,idx,indexed=true);
|
||||
|
||||
|
||||
// Function: unique()
|
||||
|
@ -1241,16 +1238,22 @@ function full_flatten(l) = [for(a=l) if(is_list(a)) (each full_flatten(a)) else
|
|||
// Internal. Not exposed.
|
||||
function _array_dim_recurse(v) =
|
||||
!is_list(v[0])
|
||||
? sum( [for(entry=v) is_list(entry) ? 1 : 0] ) == 0 ? [] : [undef]
|
||||
? len( [for(entry=v) if(!is_list(entry)) 0] ) == 0 ? [] : [undef]
|
||||
: let(
|
||||
firstlen = len(v[0]),
|
||||
first = sum( [for(entry = v) len(entry) == firstlen ? 0 : 1] ) == 0 ? firstlen : undef,
|
||||
firstlen = is_list(v[0]) ? len(v[0]): undef,
|
||||
first = len( [for(entry = v) if(! is_list(entry) || (len(entry) != firstlen)) 0 ] ) == 0 ? firstlen : undef,
|
||||
leveldown = flatten(v)
|
||||
)
|
||||
is_list(leveldown[0])
|
||||
? concat([first],_array_dim_recurse(leveldown))
|
||||
: [first];
|
||||
|
||||
function _array_dim_recurse(v) =
|
||||
let( alen = [for(vi=v) is_list(vi) ? len(vi): -1] )
|
||||
v==[] || max(alen)==-1 ? [] :
|
||||
let( add = max(alen)!=min(alen) ? undef : alen[0] )
|
||||
concat( add, _array_dim_recurse(flatten(v)));
|
||||
|
||||
|
||||
// Function: array_dim()
|
||||
// Usage:
|
||||
|
@ -1282,6 +1285,8 @@ function array_dim(v, depth=undef) =
|
|||
: let( dimlist = _array_dim_recurse(v))
|
||||
(depth > len(dimlist))? 0 : dimlist[depth-1] ;
|
||||
|
||||
|
||||
|
||||
// This function may return undef!
|
||||
|
||||
|
||||
|
|
|
@ -3,6 +3,16 @@ include <../std.scad>
|
|||
|
||||
// Section: List Query Operations
|
||||
|
||||
module test_is_homogeneous(){
|
||||
assert(is_homogeneous([[1,["a"]], [2,["b"]]])==true);
|
||||
assert(is_homogeneous([[1,["a"]], [2,[true]]])==false);
|
||||
assert(is_homogeneous([[1,["a"]], [2,[true]]],1)==true);
|
||||
assert(is_homogeneous([[1,["a"]], [2,[true]]],2)==false);
|
||||
assert(is_homogeneous([[1,["a"]], [true,["b"]]])==true);
|
||||
}
|
||||
test_is_homogeneous();
|
||||
|
||||
|
||||
module test_select() {
|
||||
l = [3,4,5,6,7,8,9];
|
||||
assert(select(l, 5, 6) == [8,9]);
|
||||
|
@ -46,7 +56,6 @@ test_in_list();
|
|||
module test_min_index() {
|
||||
assert(min_index([5,3,9,6,2,7,8,2,1])==8);
|
||||
assert(min_index([5,3,9,6,2,7,8,2,7],all=true)==[4,7]);
|
||||
// assert(min_index([],all=true)==[]);
|
||||
}
|
||||
test_min_index();
|
||||
|
||||
|
@ -54,7 +63,6 @@ test_min_index();
|
|||
module test_max_index() {
|
||||
assert(max_index([5,3,9,6,2,7,8,9,1])==2);
|
||||
assert(max_index([5,3,9,6,2,7,8,9,7],all=true)==[2,7]);
|
||||
// assert(max_index([],all=true)==[]);
|
||||
}
|
||||
test_max_index();
|
||||
|
||||
|
@ -74,6 +82,7 @@ module test_list_decreasing() {
|
|||
}
|
||||
test_list_decreasing();
|
||||
|
||||
|
||||
// Section: Basic List Generation
|
||||
|
||||
module test_repeat() {
|
||||
|
@ -155,7 +164,6 @@ module test_list_remove() {
|
|||
}
|
||||
test_list_remove();
|
||||
|
||||
|
||||
module test_list_remove_values() {
|
||||
animals = ["bat", "cat", "rat", "dog", "bat", "rat"];
|
||||
assert(list_remove_values(animals, "rat") == ["bat","cat","dog","bat","rat"]);
|
||||
|
@ -258,15 +266,24 @@ test_shuffle();
|
|||
|
||||
module test_sort() {
|
||||
assert(sort([7,3,9,4,3,1,8]) == [1,3,3,4,7,8,9]);
|
||||
assert(sort(["cat", "oat", "sat", "bat", "vat", "rat", "pat", "mat", "fat", "hat", "eat"]) == ["bat", "cat", "eat", "fat", "hat", "mat", "oat", "pat", "rat", "sat", "vat"]);
|
||||
assert(sort([[4,0],[7],[3,9],20,[4],[3,1],[8]]) == [20,[3,1],[3,9],[4],[4,0],[7],[8]]);
|
||||
assert(sort([[4,0],[7],[3,9],20,[4],[3,1],[8]],idx=1) == [[7],20,[4],[8],[4,0],[3,1],[3,9]]);
|
||||
assert(sort([[8,6],[3,1],[9,2],[4,3],[3,4],[1,5],[8,0]]) == [[1,5],[3,1],[3,4],[4,3],[8,0],[8,6],[9,2]]);
|
||||
assert(sort([[8,0],[3,1],[9,2],[4,3],[3,4],[1,5],[8,6]],idx=1) == [[8,0],[3,1],[9,2],[4,3],[3,4],[1,5],[8,6]]);
|
||||
assert(sort(["cat", "oat", "sat", "bat", "vat", "rat", "pat", "mat", "fat", "hat", "eat"])
|
||||
== ["bat", "cat", "eat", "fat", "hat", "mat", "oat", "pat", "rat", "sat", "vat"]);
|
||||
assert(sort(enumerate([[2,3,4],[1,2,3],[2,4,3]]),idx=1)==[[1,[1,2,3]], [0,[2,3,4]], [2,[2,4,3]]]);
|
||||
assert(sort([0,"1",[1,0],2,"a",[1]])== [0,2,"1","a",[1],[1,0]]);
|
||||
assert(sort([["oat",0], ["cat",1], ["bat",3], ["bat",2], ["fat",3]])== [["bat",2],["bat",3],["cat",1],["fat",3],["oat",0]]);
|
||||
}
|
||||
test_sort();
|
||||
|
||||
|
||||
module test_sortidx() {
|
||||
lst1 = ["d","b","e","c"];
|
||||
lst1 = ["da","bax","eaw","cav"];
|
||||
assert(sortidx(lst1) == [1,3,0,2]);
|
||||
lst5 = [3,5,1,7];
|
||||
assert(sortidx(lst5) == [2,0,1,3]);
|
||||
lst2 = [
|
||||
["foo", 88, [0,0,1], false],
|
||||
["bar", 90, [0,1,0], true],
|
||||
|
@ -276,11 +293,22 @@ module test_sortidx() {
|
|||
assert(sortidx(lst2, idx=1) == [3,0,2,1]);
|
||||
assert(sortidx(lst2, idx=0) == [1,2,0,3]);
|
||||
assert(sortidx(lst2, idx=[1,3]) == [3,0,2,1]);
|
||||
lst3 = [[-4, 0, 0], [0, 0, -4], [0, -4, 0], [-4, 0, 0], [0, -4, 0], [0, 0, 4], [0, 0, -4], [0, 4, 0], [4, 0, 0], [0, 0, 4], [0, 4, 0], [4, 0, 0]];
|
||||
lst3 = [[-4,0,0],[0,0,-4],[0,-4,0],[-4,0,0],[0,-4,0],[0,0,4],
|
||||
[0,0,-4],[0,4,0],[4,0,0],[0,0,4],[0,4,0],[4,0,0]];
|
||||
assert(sortidx(lst3)==[0,3,2,4,1,6,5,9,7,10,8,11]);
|
||||
assert(sortidx([[4,0],[7],[3,9],20,[4],[3,1],[8]]) == [3,5,2,4,0,1,6]);
|
||||
assert(sortidx([[4,0],[7],[3,9],20,[4],[3,1],[8]],idx=1) == [1,3,4,6,0,5,2]);
|
||||
lst4=[0,"1",[1,0],2,"a",[1]];
|
||||
assert(sortidx(lst4)== [0,3,1,4,5,2]);
|
||||
assert(sortidx(["cat","oat","sat","bat","vat","rat","pat","mat","fat","hat","eat"])
|
||||
== [3,0,10,8,9,7,1,6,5,2,4]);
|
||||
assert(sortidx([["oat",0], ["cat",1], ["bat",3], ["bat",2], ["fat",3]])== [3,2,1,4,0]);
|
||||
assert(sortidx(["Belfry", "OpenScad", "Library", "Documentation"])==[0,3,2,1]);
|
||||
assert(sortidx(["x",1,[],0,"abc",true])==[5,3,1,4,0,2]);
|
||||
}
|
||||
test_sortidx();
|
||||
|
||||
|
||||
module test_unique() {
|
||||
assert(unique([]) == []);
|
||||
assert(unique([8]) == [8]);
|
||||
|
@ -336,10 +364,8 @@ module test_set_intersection() {
|
|||
test_set_intersection();
|
||||
|
||||
|
||||
|
||||
// Arrays
|
||||
|
||||
|
||||
module test_add_scalar() {
|
||||
assert(add_scalar([1,2,3],3) == [4,5,6]);
|
||||
assert(add_scalar([[1,2,3],[3,4,5]],3) == [[4,5,6],[6,7,8]]);
|
||||
|
@ -473,6 +499,12 @@ module test_array_dim() {
|
|||
assert(array_dim([[[1,2,3],[4,5,6]],[[7,8,9],[10,11,12]]], 0) == 2);
|
||||
assert(array_dim([[[1,2,3],[4,5,6]],[[7,8,9],[10,11,12]]], 2) == 3);
|
||||
assert(array_dim([[[1,2,3],[4,5,6]],[[7,8,9]]]) == [2,undef,3]);
|
||||
assert(array_dim([1,2,3,4,5,6,7,8,9]) == [9]);
|
||||
assert(array_dim([[1],[2],[3],[4],[5],[6],[7],[8],[9]]) == [9,1]);
|
||||
assert(array_dim([]) == [0]);
|
||||
assert(array_dim([[]]) == [1,0]);
|
||||
assert(array_dim([[],[]]) == [2,0]);
|
||||
assert(array_dim([[],[1]]) == [2,undef]);
|
||||
}
|
||||
test_array_dim();
|
||||
|
||||
|
@ -486,7 +518,4 @@ module test_transpose() {
|
|||
test_transpose();
|
||||
|
||||
|
||||
cube();
|
||||
|
||||
|
||||
// vim: expandtab tabstop=4 shiftwidth=4 softtabstop=4 nowrap
|
||||
|
|
Loading…
Reference in a new issue