From 9da0523bf16c4dfeeb3dbf1e7f862e2c0e6eae5f Mon Sep 17 00:00:00 2001 From: Revar Desmera Date: Mon, 21 Oct 2019 03:44:29 -0700 Subject: [PATCH] Added stack.scad --- stack.scad | 193 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 193 insertions(+) create mode 100644 stack.scad diff --git a/stack.scad b/stack.scad new file mode 100644 index 00000000..bb14c0a6 --- /dev/null +++ b/stack.scad @@ -0,0 +1,193 @@ +////////////////////////////////////////////////////////////////////// +// LibFile: stack.scad +// Stack data structure implementation. +// To use, add the following lines to the beginning of your file: +// ``` +// use +// use +// ``` +////////////////////////////////////////////////////////////////////// + + +// Section: Stack Data Structure +// A stack is a last-in-first-out collection of items. You can push items onto the top of the +// stack, or pop the top item off. While you can treat a stack as an opaque data type, using the +// functions below, it's simply implemented as a list. This means that you can use any list +// function to manipulate the stack. The last item in the list is the topmost stack item. +// The depth of an item is how far buried in the stack that item is. An item at depth 1 is the +// top-most stack item. An item at depth 3 is two items below the top-most stack item. + + +// Function: stack_init() +// Usage: +// stack = stack_init(); +// Description: +// Creates an empty stack/list. +// Example: +// stack = stack_init(); // Return: [] +function stack_init() = []; + + +// Function: stack_empty() +// Usage: +// if (stack_empty(stack)) ... +// Description: +// Returns true if the given stack is empty. +// Arguments: +// stack = The stack to test if empty. +// Example: +// stack = stack_init(); +// is_empty = stack_empty(stack); // Returns: true +// stack2 = stack_push(stack, "foo"); +// is_empty2 = stack_empty(stack2); // Returns: false +function stack_empty(stack) = + assert(is_list(stack)) + len(stack)==0; + + +// Function: stack_depth() +// Usage: +// depth = stack_depth(stack); +// Description: +// Returns the depth of the given stack. +// Arguments: +// stack = The stack to get the depth of. +// Example: +// stack = stack_init(); +// depth = stack_depth(stack); // Returns: 0 +// stack2 = stack_push(stack, "foo"); +// depth2 = stack_depth(stack2); // Returns: 1 +// stack3 = stack_push(stack2, ["bar","baz","qux"]); +// depth3 = stack_depth(stack3); // Returns: 4 +function stack_depth(stack) = + assert(is_list(stack)) + len(stack); + + +// Function: stack_top() +// Usage: +// item = stack_top(stack); +// list = stack_top(stack,n); +// Description: +// If n is not given, returns the topmost item of the given stack. +// If n is given, returns a list of the `n` topmost items. +// Arguments: +// stack = The stack/list to get the top item(s) of. +// Example: +// stack = [4,5,6,7]; +// item = stack_top(stack); // Returns: 7 +// list = stack_top(stack,n=3); // Returns: [5,6,7] +function stack_top(stack,n=undef) = + assert(is_list(stack)) + is_undef(n)? ( + stack[len(stack)-1] + ) : ( + let(stacksize = len(stack)) + assert(is_num(n)) + assert(n>=0) + assert(stacksize>=n, "stack underflow") + [for (i=[0:1:n-1]) stack[stacksize-n+i]] + ); + + +// Function: stack_peek() +// Usage: +// item = stack_peek(stack,[depth]); +// list = stack_peek(stack,depth,n); +// Description: +// If `n` is not given, returns the stack item at depth `depth`. +// If `n` is given, returns a list of the `n` stack items at and above depth `depth`. +// Arguments: +// stack = The stack to read from. +// depth = The depth of the stack item to read. Default: 1 +// n = The number of stack items to return. Default: undef (Return only the stack item at `depth`) +// Example: +// stack = [2,3,4,5,6,7,8,9]; +// item = stack_peek(stack); // Returns: 9 +// item2 = stack_peek(stack, 3); // Returns: 7 +// list = stack_peek(stack, 6, 4); // Returns: [4,5,6,7] +function stack_peek(stack,depth=1,n=undef) = + assert(is_list(stack)) + assert(is_num(depth)) + assert(depth>0) + let(stacksize = len(stack)) + assert(stacksize>=depth, "stack underflow") + is_undef(n)? ( + stack[stacksize-depth] + ) : ( + assert(is_num(n)) + assert(n>=0) + assert(n=0) + assert(len(stack)>=n, "stack underflow") + [for (i = [0:1:len(stack)-1-n]) stack[i]]; + + +// Function: stack_rotate() +// Usage: +// modified_stack = stack_rotate(stack, [n]); +// Description: +// Rotates the top `abs(n)` stack items, and returns the modified stack. +// If `n` is positive, then the depth `n` stack item is rotated (left) to the top. +// If `n` is negative, then the top stack item is rotated (right) to depth `abs(n)`. +// Arguments: +// stack = The stack to modify. +// n = The number of stack items to rotate. If negative, reverse rotation direction. Default: 3 +// Example: +// stack = [4,5,6,7,8]; +// stack2 = stack_rotate(stack,3); // Returns: [4,5,7,8,6] +// stack3 = stack_rotate(stack2,-4); // Returns: [4,6,5,7,8] +function stack_rotate(stack,n=3) = + assert(is_list(stack)) + let(stacksize = len(stack)) + assert(stacksize>=n, "stack underflow") + n>=0? concat( + [for (i=[0:1:stacksize-1-n]) stack[i]], + [for (i=[0:1:n-2]) stack[stacksize-n+i+1]], + [stack[stacksize-n]] + ) : concat( + [for (i=[0:1:stacksize-1+n]) stack[i]], + [stack[stacksize-1]], + [for (i=[0:1:-n-2]) stack[stacksize+n+i]] + ); + + +// vim: noexpandtab tabstop=4 shiftwidth=4 softtabstop=4 nowrap