diff --git a/arrays.scad b/arrays.scad index 700e8a8..289ce24 100644 --- a/arrays.scad +++ b/arrays.scad @@ -153,7 +153,35 @@ function list_range(n=undef, s=0, e=undef, step=undef) = // list = The list to reverse. // Example: // reverse([3,4,5,6]); // Returns [6,5,4,3] -function reverse(list) = [ for (i = [len(list)-1 : -1 : 0]) list[i] ]; +function reverse(list) = + assert(is_list(list)||is_string(list)) + [ for (i = [len(list)-1 : -1 : 0]) list[i] ]; + + +// Function: list_rotate() +// Usage: +// rlist = list_rotate(list,n); +// Description: +// Rotates the contents of a list by `n` positions left. +// If `n` is negative, then the rotation is `abs(n)` positions to the right. +// Arguments: +// list = The list to rotate. +// n = The number of positions to rotate by. If negative, rotated to the right. Positive rotates to the left. Default: 1 +// Example: +// l1 = list_rotate([1,2,3,4,5],-2); // Returns: [4,5,1,2,3] +// l2 = list_rotate([1,2,3,4,5],-1); // Returns: [5,1,2,3,4] +// l3 = list_rotate([1,2,3,4,5],0); // Returns: [1,2,3,4,5] +// l4 = list_rotate([1,2,3,4,5],1); // Returns: [2,3,4,5,1] +// l5 = list_rotate([1,2,3,4,5],2); // Returns: [3,4,5,1,2] +// l6 = list_rotate([1,2,3,4,5],3); // Returns: [4,5,1,2,3] +// l7 = list_rotate([1,2,3,4,5],4); // Returns: [5,1,2,3,4] +// l8 = list_rotate([1,2,3,4,5],5); // Returns: [1,2,3,4,5] +// l9 = list_rotate([1,2,3,4,5],6); // Returns: [2,3,4,5,1] +function list_rotate(list,n=1) = + assert(is_list(list)||is_string(list)) + assert(is_num(n)) + let(n = posmod(n,len(list))) + n==0? list : concat(select(list,n,-1), select(list,0,n-1)); // Function: deduplicate() @@ -172,6 +200,7 @@ function reverse(list) = [ for (i = [len(list)-1 : -1 : 0]) list[i] ]; // deduplicate("Hello"); // Returns: ["H","e","l","o"] // deduplicate([[3,4],[7,2],[7,1.99],[1,4]],eps=0.1); // Returns: [[3,4],[7,2],[1,4]] function deduplicate(list, closed=false, eps=EPSILON) = + assert(is_list(list)||is_string(list)) let( l = len(list), end = l-(closed?0:1) @@ -201,6 +230,7 @@ function deduplicate(list, closed=false, eps=EPSILON) = // list_set([2,3,4,5], 2, 21); // Returns: [2,3,21,5] // list_set([2,3,4,5], [1,3], [81,47]); // Returns: [2,81,4,47] function list_set(list=[],indices,values,dflt=0,minlen=0) = + assert(is_list(list)||is_string(list)) !is_list(indices)? ( (is_num(indices) && indicesp.y) true])==0; @@ -372,6 +409,7 @@ function list_increasing(list,ind=0) = // list_decreasing([4,2,3,1]); // Returns: false // list_decreasing([4,3,2,1]); // Returns: true function list_decreasing(list) = + assert(is_list(list)||is_string(list)) len([for (p=pair(list)) if(p.xlength)? list_trim(v,length) : list_pad(v,length,fill); @@ -441,6 +484,7 @@ function list_fit(v, length, fill) = // colors = ["red", "green", "blue"]; // for (i=idx(colors)) right(20*i) color(colors[i]) circle(d=10); function idx(list, step=1, end=-1,start=0) = + assert(is_list(list)||is_string(list)) [start : step : len(list)+end]; @@ -459,6 +503,7 @@ function idx(list, step=1, end=-1,start=0) = // colors = ["red", "green", "blue"]; // for (p=enumerate(colors)) right(20*p[0]) color(p[1]) circle(d=10); function enumerate(l,idx=undef) = + assert(is_list(l)||is_string(list)) (idx==undef)? [for (i=[0:1:len(l)-1]) [i,l[i]]] : [for (i=[0:1:len(l)-1]) concat([i], [for (j=idx) l[i][j]])]; @@ -468,6 +513,7 @@ function enumerate(l,idx=undef) = // Description: // Shuffles the input list into random order. function shuffle(list) = + assert(is_list(l)||is_string(list)) len(list)<=1 ? list : let ( rval = rands(0,1,len(list)), @@ -688,6 +734,7 @@ function sortidx(list, idx=undef) = // Arguments: // arr = The list to uniquify. function unique(arr) = + assert(is_list(arr)||is_string(list)) len(arr)<=1? arr : let( sorted = sort(arr) ) [ @@ -728,7 +775,9 @@ function subindex(v, idx) = [ // Example: // l = ["A","B","C",D"]; // echo([for (p=pair(l)) str(p.y,p.x)]); // Outputs: ["BA", "CB", "DC"] -function pair(v) = [for (i=[0:1:len(v)-2]) [v[i],v[i+1]]]; +function pair(v) = + assert(is_list(v)||is_string(v)) + [for (i=[0:1:len(v)-2]) [v[i],v[i+1]]]; // Function: pair_wrap() @@ -739,7 +788,9 @@ function pair(v) = [for (i=[0:1:len(v)-2]) [v[i],v[i+1]]]; // Example: // l = ["A","B","C","D"]; // echo([for (p=pair_wrap(l)) str(p.y,p.x)]); // Outputs: ["BA", "CB", "DC", "AD"] -function pair_wrap(v) = [for (i=[0:1:len(v)-1]) [v[i],v[(i+1)%len(v)]]]; +function pair_wrap(v) = + assert(is_list(v)||is_string(v)) + [for (i=[0:1:len(v)-1]) [v[i],v[(i+1)%len(v)]]]; // Function: triplet() @@ -750,7 +801,9 @@ function pair_wrap(v) = [for (i=[0:1:len(v)-1]) [v[i],v[(i+1)%len(v)]]]; // Example: // l = ["A","B","C","D","E"]; // echo([for (p=triplet(l)) str(p.z,p.y,p.x)]); // Outputs: ["CBA", "DCB", "EDC"] -function triplet(v) = [for (i=[0:1:len(v)-3]) [v[i],v[i+1],v[i+2]]]; +function triplet(v) = + assert(is_list(v)||is_string(v)) + [for (i=[0:1:len(v)-3]) [v[i],v[i+1],v[i+2]]]; // Function: triplet_wrap() @@ -761,7 +814,9 @@ function triplet(v) = [for (i=[0:1:len(v)-3]) [v[i],v[i+1],v[i+2]]]; // Example: // l = ["A","B","C","D"]; // echo([for (p=triplet_wrap(l)) str(p.z,p.y,p.x)]); // Outputs: ["CBA", "DCB", "ADC", "BAD"] -function triplet_wrap(v) = [for (i=[0:1:len(v)-1]) [v[i],v[(i+1)%len(v)],v[(i+2)%len(v)]]]; +function triplet_wrap(v) = + assert(is_list(v)||is_string(v)) + [for (i=[0:1:len(v)-1]) [v[i],v[(i+1)%len(v)],v[(i+2)%len(v)]]]; // Function: zip() diff --git a/tests/test_arrays.scad b/tests/test_arrays.scad index 584c55b..5f28b0d 100644 --- a/tests/test_arrays.scad +++ b/tests/test_arrays.scad @@ -65,6 +65,21 @@ module test_reverse() { test_reverse(); +module test_list_rotate() { + assert(list_rotate([1,2,3,4,5],-2) == [4,5,1,2,3]); + assert(list_rotate([1,2,3,4,5],-1) == [5,1,2,3,4]); + assert(list_rotate([1,2,3,4,5],0) == [1,2,3,4,5]); + assert(list_rotate([1,2,3,4,5],1) == [2,3,4,5,1]); + assert(list_rotate([1,2,3,4,5],2) == [3,4,5,1,2]); + assert(list_rotate([1,2,3,4,5],3) == [4,5,1,2,3]); + assert(list_rotate([1,2,3,4,5],4) == [5,1,2,3,4]); + assert(list_rotate([1,2,3,4,5],5) == [1,2,3,4,5]); + assert(list_rotate([1,2,3,4,5],6) == [2,3,4,5,1]); + assert(list_rotate([],3) == []); +} +test_list_rotate(); + + module test_deduplicate() { assert(deduplicate([8,3,4,4,4,8,2,3,3,8,8]) == [8,3,4,8,2,3,8]); assert(deduplicate(closed=true, [8,3,4,4,4,8,2,3,3,8,8]) == [8,3,4,8,2,3]);