diff --git a/.nycrc.json b/.nycrc.json index 22f3ed8..76620cd 100644 --- a/.nycrc.json +++ b/.nycrc.json @@ -3,11 +3,7 @@ "all": true, "check-coverage": true, "exclude": [ - "**/*.d.ts", - "src/array/**/*", - "src/heap/**/*", - "src/segmentTree/**/*", - "src/trie/**/*" + "src/TODO/**/*" ], "extension": [".ts", ".tsx"], "include": [ diff --git a/README.md b/README.md index 583f5c4..357996f 100644 --- a/README.md +++ b/README.md @@ -2,6 +2,7 @@ [![npm](https://img.shields.io/npm/v/dastal.svg)](https://www.npmjs.com/package/dastal) [![types](https://img.shields.io/npm/types/dastal)](https://www.npmjs.com/package/dastal) +[![nycrc config on GitHub](https://img.shields.io/nycrc/havelessbemore/dastal?config=.nycrc.json)](https://www.npmjs.com/package/dastal) Data structures & algorithms implementations for node diff --git a/dist/dastal.min.js b/dist/dastal.min.js index 980f9d0..c7fd061 100644 --- a/dist/dastal.min.js +++ b/dist/dastal.min.js @@ -1,2 +1,2 @@ -!function(t,e){"object"==typeof exports&&"object"==typeof module?module.exports=e():"function"==typeof define&&define.amd?define("Dastal",[],e):"object"==typeof exports?exports.Dastal=e():t.Dastal=e()}(self,(function(){return(()=>{var t={125:(t,e,r)=>{"use strict";r.d(e,{S:()=>h});var n,i=r(557);function a(t){return function(t){if(Array.isArray(t))return l(t)}(t)||function(t){if("undefined"!=typeof Symbol&&null!=t[Symbol.iterator]||null!=t["@@iterator"])return Array.from(t)}(t)||o(t)||function(){throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}()}function u(t,e){var r="undefined"!=typeof Symbol&&t[Symbol.iterator]||t["@@iterator"];if(!r){if(Array.isArray(t)||(r=o(t))||e&&t&&"number"==typeof t.length){r&&(t=r);var n=0,i=function(){};return{s:i,n:function(){return n>=t.length?{done:!0}:{done:!1,value:t[n++]}},e:function(t){throw t},f:i}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}var a,u=!0,l=!1;return{s:function(){r=r.call(t)},n:function(){var t=r.next();return u=t.done,t},e:function(t){l=!0,a=t},f:function(){try{u||null==r.return||r.return()}finally{if(l)throw a}}}}function o(t,e){if(t){if("string"==typeof t)return l(t,e);var r=Object.prototype.toString.call(t).slice(8,-1);return"Object"===r&&t.constructor&&(r=t.constructor.name),"Map"===r||"Set"===r?Array.from(t):"Arguments"===r||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(r)?l(t,e):void 0}}function l(t,e){(null==e||e>t.length)&&(e=t.length);for(var r=0,n=new Array(e);r=0&&t<=this.size&&this.array.splice(t,0,e),this.size}},{key:"addAll",value:function(t,e){if(t>=0&&t<=this.size){var r,n=u((0,i.dC)(1e4,e));try{for(n.s();!(r=n.n()).done;){var o,l=r.value;(o=this.array).splice.apply(o,[t,0].concat(a(l))),t+=l.length}}catch(t){n.e(t)}finally{n.f()}}return this.size}},{key:"clear",value:function(){this.array.length=0}},{key:"concat",value:function(){for(var e=new t(this),r=arguments.length,n=new Array(r),i=0;i=this.size?void 0:this.array[t]}},{key:"getSet",value:function(t,e){var r=void 0;return t>=0&&t=this.size?void 0:this.array.splice(t,1)[0]}},{key:"reverse",value:function(t,e){var r,n;for(t=(0,i.re)(null!==(r=t)&&void 0!==r?r:0,0,this.size),e=(0,i.re)(null!==(n=e)&&void 0!==n?n:this.size,0,this.size)-1;t=0&&t=0?function(){return Math.min(r,u.size)}:function(){return u.size+r};case 2:if(!(e{"use strict";r.d(e,{s:()=>l});var n,i=r(557);function a(t,e){(null==e||e>t.length)&&(e=t.length);for(var r=0,n=new Array(e);rthis.length)return this.length;var r=this._get(t-1),n={next:r.next,prev:r,value:e};return r.next=n,n.next.prev=n,++this.length}},{key:"addAll",value:function(t,e){return t>=0&&t<=this.length&&this._addAll(this._get(t),e),this.length}},{key:"clear",value:function(){this.length=0,this.root.prev=this.root.next=this.root}},{key:"concat",value:function(){for(var e=new t(this),r=arguments.length,n=new Array(r),i=0;i=(r=e+Math.min(r-e,this.length-t)))return this;if(e=this.length?void 0:this._get(t).value}},{key:"getSet",value:function(t,e){if(!(t<0||t>=this.length)){var r=this._get(t),n=r.value;return r.value=e(r.value),n}}},{key:"pop",value:function(){if(!(this.length<1)){var t=this.root.prev;return t.prev.next=this.root,this.root.prev=t.prev,--this.length,t.value}}},{key:"push",value:function(t){var e=this.root.prev,r={next:this.root,prev:e,value:t};return e.next=this.root.prev=r,++this.length}},{key:"remove",value:function(t){if(!(t<0||t>=this.length)){var e=this._get(t);return e.prev.next=e.next,e.next.prev=e.prev,--this.length,e.value}}},{key:"reverse",value:function(t,e){var r,n;if(t=(0,i.re)(null!==(r=t)&&void 0!==r?r:0,0,this.length),(e=(0,i.re)(null!==(n=e)&&void 0!==n?n:this.length,0,this.length))-t<2)return this;var a=this._get(t-1),u=a.next,o=u;do{var l=o.next;o.next=o.prev,o.prev=l,a.next=o,o=l}while(++t=this.length)){var r=this._get(t),n=r.value;return r.value=e,n}}},{key:"shift",value:function(){if(!(this.length<1)){var t=this.root.next;return t.next.prev=this.root,this.root.next=t.next,--this.length,t.value}}},{key:"size",get:function(){return this.length}},{key:"slice",value:function(e,r){return new t(this.view(e,r))}},{key:"splice",value:function(e,r,n){var a,u;e=(0,i.re)(null!==(a=e)&&void 0!==a?a:0,0,this.size),r=(0,i.uZ)(null!==(u=r)&&void 0!==u?u:this.size,0,this.size-e);var o=new t;if(null==n&&r<1)return o;for(var l=this._get(e);r-- >0;)o.push(l.value),l.prev.next=l.next,l.next.prev=l.prev,l=l.next,--this.length;return this._addAll(l,null!=n?n:[]),o}},{key:n,value:regeneratorRuntime.mark((function t(){var e;return regeneratorRuntime.wrap((function(t){for(;;)switch(t.prev=t.next){case 0:e=this.root.next;case 1:if(e===this.root){t.next=7;break}return t.next=4,e.value;case 4:e=e.next,t.next=1;break;case 7:case"end":return t.stop()}}),t,this)}))},{key:"unshift",value:function(t){var e=this.root.next,r={next:e,prev:this.root,value:t};return this.root.next=e.prev=r,++this.length}},{key:"update",value:function(t,e,r){var n,a;if(null==r&&(arguments.length<2?(r=t,t=void 0):(r=e,e=void 0)),(t=(0,i.re)(null!==(n=t)&&void 0!==n?n:0,0,this.length))<(e=(0,i.re)(null!==(a=e)&&void 0!==a?a:this.length,0,this.length))){var u=this._get(t);do{u.value=r(u.value,t),u=u.next}while(++t=0?function(){return r}:function(){return o.length+r})())){t.next=8;break}u=this._get(e);case 4:return t.next=6,u.value;case 6:u=u.next;case 7:if(++e=t.length?{done:!0}:{done:!1,value:t[n++]}},e:function(t){throw t},f:i}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}var u,o=!0,l=!1;return{s:function(){r=r.call(t)},n:function(){var t=r.next();return o=t.done,t},e:function(t){l=!0,u=t},f:function(){try{o||null==r.return||r.return()}finally{if(l)throw u}}}}(e);try{for(i.s();!(r=i.n()).done;){var u={prev:n,value:r.value};n.next=u,n=u,++this.length}}catch(t){i.e(t)}finally{i.f()}n.next=t,t.prev=n}},{key:"_get",value:function(t){var e=this.root;if(t=0;)e=e.next;else for(t=this.length-t;t>0;--t)e=e.prev;return e}}])&&u(e.prototype,r),t}()},372:(t,e,r)=>{"use strict";r.r(e),r.d(e,{ArrayList:()=>n.S,DoublyLinkedList:()=>i.s,LinkedList:()=>a.S});var n=r(125),i=r(736),a=r(148),u=r(241),o={};for(const t in u)["default","ArrayList","DoublyLinkedList","LinkedList"].indexOf(t)<0&&(o[t]=()=>u[t]);r.d(e,o)},148:(t,e,r)=>{"use strict";r.d(e,{S:()=>l});var n,i=r(557);function a(t,e){(null==e||e>t.length)&&(e=t.length);for(var r=0,n=new Array(e);r=0&&t=0&&t=(r=e+Math.min(r-e,this.length-t)))return this;if(tr){var o=this._get(e-1);return this._copyWithin(o,this._get(t-e-1,o),r-e),this}var l=this._get(e-1),s=this._get(r-e-1,l),h=this._copyWithin(l,s,t-e);t+(r-e)>=this.length&&(this.tail=s);var f=l.next;return l.next=s.next,s.next=h.next,h.next=f,this}},{key:"fill",value:function(t,e,r){var n,a;if((e=(0,i.re)(null!==(n=e)&&void 0!==n?n:0,0,this.length))<(r=(0,i.re)(null!==(a=r)&&void 0!==a?a:this.length,0,this.length))){var u=this._get(e);do{u.value=t,u=u.next}while(++e=this.length))return t=this.length)){var r=t=this.length)){var e=this._get(t-1),r=e.next;return e.next=r.next,t===--this.length&&(this.tail=e),r.value}}},{key:"reverse",value:function(t,e){var r,n;if(t=(0,i.re)(null!==(r=t)&&void 0!==r?r:0,0,this.length),(e=(0,i.re)(null!==(n=e)&&void 0!==n?n:this.length,0,this.length))-t<2)return this;var a=this._get(t-1);this.tail=e>=this.length?a.next:this.tail;for(var u=a.next,o=u,l=u.next;++t=this.length)){var r=this._get(t),n=r.value;return r.value=e,n}}},{key:"shift",value:function(){return this.remove(0)}},{key:"size",get:function(){return this.length}},{key:"slice",value:function(e,r){return new t(this.view(e,r))}},{key:"splice",value:function(e,r,n){var a,u;e=(0,i.re)(null!==(a=e)&&void 0!==a?a:0,0,this.size),r=(0,i.uZ)(null!==(u=r)&&void 0!==u?u:this.size,0,this.size-e);var o=new t;if(null==n&&r<1)return o;for(var l=this._get(e-1),s=e+r>=this.size;r-- >0;){var h=l.next;o.push(h.value),l.next=h.next,--this.length}return l=this._addAll(l,null!=n?n:[]),this.tail=s?l:this.tail,o}},{key:n,value:regeneratorRuntime.mark((function t(){var e;return regeneratorRuntime.wrap((function(t){for(;;)switch(t.prev=t.next){case 0:e=this.root.next;case 1:if(e===this.root){t.next=7;break}return t.next=4,e.value;case 4:e=e.next,t.next=1;break;case 7:case"end":return t.stop()}}),t,this)}))},{key:"unshift",value:function(t){return this.add(0,t)}},{key:"update",value:function(t,e,r){var n,a;if(null==r&&(arguments.length<2?(r=t,t=void 0):(r=e,e=void 0)),(t=(0,i.re)(null!==(n=t)&&void 0!==n?n:0,0,this.length))<(e=(0,i.re)(null!==(a=e)&&void 0!==a?a:this.length,0,this.length))){var u=this._get(t);do{u.value=r(u.value,t),u=u.next}while(++t=0?function(){return r}:function(){return o.length+r})())){t.next=8;break}u=this._get(e);case 4:return t.next=6,u.value;case 6:u=u.next;case 7:if(++e=t.length?{done:!0}:{done:!1,value:t[n++]}},e:function(t){throw t},f:i}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}var u,o=!0,l=!1;return{s:function(){r=r.call(t)},n:function(){var t=r.next();return o=t.done,t},e:function(t){l=!0,u=t},f:function(){try{o||null==r.return||r.return()}finally{if(l)throw u}}}}(e);try{for(i.s();!(r=i.n()).done;){var u={value:r.value};t.next=u,t=u,++this.length}}catch(t){i.e(t)}finally{i.f()}return t.next=n,t}},{key:"_copyWithin",value:function(t,e,r){for(;r-- >0;)t=t.next,(e=e.next).value=t.value;return e}},{key:"_get",value:function(t){for(var e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:this.root,r=e;t-- >=0;)r=r.next;return r}}])&&u(e.prototype,r),t}()},241:()=>{},451:(t,e,r)=>{"use strict";var n;function i(t,e){for(var r=0;ra}),n=Symbol.iterator;var a=function(){function t(e){var r,n;!function(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}(this,t),n=void 0,(r="array")in this?Object.defineProperty(this,r,{value:n,enumerable:!0,configurable:!0,writable:!0}):this[r]=n,this.array=e?Array.from(e):[]}var e,r;return e=t,(r=[{key:"clear",value:function(){this.array.length=0}},{key:"dequeue",value:function(){return this.size<1?void 0:this.array.shift()}},{key:"enqueue",value:function(t){return this.array.push(t)}},{key:"peek",value:function(){return this.size<1?void 0:this.array[0]}},{key:"size",get:function(){return this.array.length}},{key:n,value:function(){return this.array[Symbol.iterator]()}}])&&i(e.prototype,r),t}()},753:(t,e,r)=>{"use strict";r.r(e),r.d(e,{ArrayQueue:()=>n.H,LinkedQueue:()=>i.S});var n=r(451),i=r(519),a=r(786),u={};for(const t in a)["default","ArrayQueue","LinkedQueue"].indexOf(t)<0&&(u[t]=()=>a[t]);r.d(e,u)},519:(t,e,r)=>{"use strict";r.d(e,{S:()=>u});var n,i=r(148);function a(t,e){for(var r=0;r{},909:(t,e,r)=>{"use strict";var n;function i(t,e){for(var r=0;ra}),n=Symbol.iterator;var a=function(){function t(e){var r,n;!function(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}(this,t),n=void 0,(r="array")in this?Object.defineProperty(this,r,{value:n,enumerable:!0,configurable:!0,writable:!0}):this[r]=n,this.array=e?Array.from(e):[]}var e,r;return e=t,(r=[{key:"clear",value:function(){this.array.length=0}},{key:"peek",value:function(){return this.array[this.array.length-1]}},{key:"pop",value:function(){return this.array.pop()}},{key:"push",value:function(t){return this.array.push(t)}},{key:"size",get:function(){return this.array.length}},{key:n,value:regeneratorRuntime.mark((function t(){var e,r;return regeneratorRuntime.wrap((function(t){for(;;)switch(t.prev=t.next){case 0:e=this.array,r=e.length;case 2:if(!(r>0)){t.next=7;break}case 3:return t.next=5,e[--r];case 5:t.next=2;break;case 7:case"end":return t.stop()}}),t,this)}))}])&&i(e.prototype,r),t}()},610:(t,e,r)=>{"use strict";r.r(e),r.d(e,{ArrayStack:()=>n.O,LinkedStack:()=>i._});var n=r(909),i=r(150),a=r(173),u={};for(const t in a)["default","ArrayStack","LinkedStack"].indexOf(t)<0&&(u[t]=()=>a[t]);r.d(e,u)},150:(t,e,r)=>{"use strict";r.d(e,{_:()=>o});var n,i=r(148);function a(t,e){(null==e||e>t.length)&&(e=t.length);for(var r=0,n=new Array(e);r=t.length?{done:!0}:{done:!1,value:t[n++]}},e:function(t){throw t},f:i}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}var u,o=!0,l=!1;return{s:function(){r=r.call(t)},n:function(){var t=r.next();return o=t.done,t},e:function(t){l=!0,u=t},f:function(){try{o||null==r.return||r.return()}finally{if(l)throw u}}}}(e||[]);try{for(o.s();!(u=o.n()).done;){var l=u.value;this.push(l)}}catch(t){o.e(t)}finally{o.f()}}var e,r;return e=t,(r=[{key:"clear",value:function(){this.list.clear()}},{key:"peek",value:function(){return this.list.get(0)}},{key:"pop",value:function(){return this.list.shift()}},{key:"push",value:function(t){return this.list.unshift(t)}},{key:"size",get:function(){return this.list.size}},{key:n,value:function(){return this.list[Symbol.iterator]()}}])&&u(e.prototype,r),t}()},173:()=>{},557:(t,e,r)=>{"use strict";r.d(e,{dC:()=>u,uZ:()=>o,re:()=>l});var n=regeneratorRuntime.mark(u);function i(t,e){var r="undefined"!=typeof Symbol&&t[Symbol.iterator]||t["@@iterator"];if(!r){if(Array.isArray(t)||(r=function(t,e){if(t){if("string"==typeof t)return a(t,e);var r=Object.prototype.toString.call(t).slice(8,-1);return"Object"===r&&t.constructor&&(r=t.constructor.name),"Map"===r||"Set"===r?Array.from(t):"Arguments"===r||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(r)?a(t,e):void 0}}(t))||e&&t&&"number"==typeof t.length){r&&(t=r);var n=0,i=function(){};return{s:i,n:function(){return n>=t.length?{done:!0}:{done:!1,value:t[n++]}},e:function(t){throw t},f:i}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}var u,o=!0,l=!1;return{s:function(){r=r.call(t)},n:function(){var t=r.next();return o=t.done,t},e:function(t){l=!0,u=t},f:function(){try{o||null==r.return||r.return()}finally{if(l)throw u}}}}function a(t,e){(null==e||e>t.length)&&(e=t.length);for(var r=0,n=new Array(e);r=t)){n.next=10;break}return n.next=9,r;case 9:r=[];case 10:n.next=4;break;case 12:n.next=17;break;case 14:n.prev=14,n.t0=n.catch(2),a.e(n.t0);case 17:return n.prev=17,a.f(),n.finish(17);case 20:if(!(r.length>0)){n.next=23;break}return n.next=23,r;case 23:case"end":return n.stop()}}),n,null,[[2,14,17,20]])}function o(t,e,r){return Math.min(r,Math.max(e,t))}function l(t,e,r){return o(t<0?r+t:t,e,r)}}},e={};function r(n){var i=e[n];if(void 0!==i)return i.exports;var a=e[n]={exports:{}};return t[n](a,a.exports,r),a.exports}r.n=t=>{var e=t&&t.__esModule?()=>t.default:()=>t;return r.d(e,{a:e}),e},r.d=(t,e)=>{for(var n in e)r.o(e,n)&&!r.o(t,n)&&Object.defineProperty(t,n,{enumerable:!0,get:e[n]})},r.o=(t,e)=>Object.prototype.hasOwnProperty.call(t,e),r.r=t=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(t,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(t,"__esModule",{value:!0})};var n={};return(()=>{"use strict";r.r(n);var t=r(372),e={};for(const r in t)"default"!==r&&(e[r]=()=>t[r]);r.d(n,e);var i=r(753);e={};for(const t in i)["default","ArrayList","DoublyLinkedList","LinkedList"].indexOf(t)<0&&(e[t]=()=>i[t]);r.d(n,e);var a=r(610);e={};for(const t in a)["default","ArrayList","DoublyLinkedList","LinkedList","ArrayQueue","LinkedQueue"].indexOf(t)<0&&(e[t]=()=>a[t]);r.d(n,e)})(),n})()})); +!function(t,e){"object"==typeof exports&&"object"==typeof module?module.exports=e():"function"==typeof define&&define.amd?define("Dastal",[],e):"object"==typeof exports?exports.Dastal=e():t.Dastal=e()}(self,(function(){return(()=>{var t={352:(t,e,r)=>{"use strict";r.d(e,{L:()=>h});var n,i=4294967295,a=r(565);function o(t,e){var r="undefined"!=typeof Symbol&&t[Symbol.iterator]||t["@@iterator"];if(!r){if(Array.isArray(t)||(r=function(t,e){if(t){if("string"==typeof t)return u(t,e);var r=Object.prototype.toString.call(t).slice(8,-1);return"Object"===r&&t.constructor&&(r=t.constructor.name),"Map"===r||"Set"===r?Array.from(t):"Arguments"===r||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(r)?u(t,e):void 0}}(t))||e&&t&&"number"==typeof t.length){r&&(t=r);var n=0,i=function(){};return{s:i,n:function(){return n>=t.length?{done:!0}:{done:!1,value:t[n++]}},e:function(t){throw t},f:i}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}var a,o=!0,l=!1;return{s:function(){r=r.call(t)},n:function(){var t=r.next();return o=t.done,t},e:function(t){l=!0,a=t},f:function(){try{o||null==r.return||r.return()}finally{if(l)throw a}}}}function u(t,e){(null==e||e>t.length)&&(e=t.length);for(var r=0,n=new Array(e);r=i)throw new RangeError("Invalid heap length");r.push(l)}}catch(t){u.e(t)}finally{u.f()}return n=0}},{key:"delete",value:function(t){var e=this.array.indexOf(t);if(e<0)return!1;var r=this.array.pop();return e>=this.array.length||(this.array[e]=r,(0,a.AV)(e,this.compare,this.array),(0,a.$f)(e,this.compare,this.array)),!0}},{key:"dump",value:regeneratorRuntime.mark((function t(){var e,r,n;return regeneratorRuntime.wrap((function(t){for(;;)switch(t.prev=t.next){case 0:e=o(this.array),t.prev=1,e.s();case 3:if((r=e.n()).done){t.next=9;break}return n=r.value,t.next=7,n;case 7:t.next=3;break;case 9:t.next=14;break;case 11:t.prev=11,t.t0=t.catch(1),e.e(t.t0);case 14:return t.prev=14,e.f(),t.finish(14);case 17:case"end":return t.stop()}}),t,this,[[1,11,14,17]])}))},{key:"merge",value:function(e){var r=this.array;if(e.size<1)return this;if(r.length+e.size>i)throw new RangeError("Invalid heap length");var n,u=o(e instanceof t?e.array:e.dump());try{for(u.s();!(n=u.n()).done;){var l=n.value;r.push(l)}}catch(t){u.e(t)}finally{u.f()}return(0,a.g3)(this.compare,r),this}},{key:"peek",value:function(){return this.array.length>0?this.array[0]:void 0}},{key:"pop",value:function(){if(!(this.array.length<1)){var t=this.array[0],e=this.array.pop();return this.array.length>0&&(this.array[0]=e,(0,a.AV)(0,this.compare,this.array)),t}}},{key:"push",value:function(t){return this.array.push(t),(0,a.$f)(this.array.length-1,this.compare,this.array),this.size}},{key:"pushPop",value:function(t){if(this.array.length<1||this.compare(t,this.array[0])<=0)return t;var e=this.array[0];return this.array[0]=t,(0,a.AV)(0,this.compare,this.array),e}},{key:"replace",value:function(t){if(!(this.array.length<1)){var e=this.array[0];return this.array[0]=t,t=e,(0,a.AV)(0,this.compare,this.array),t}this.array.push(t)}},{key:"size",get:function(){return this.array.length}},{key:n,value:regeneratorRuntime.mark((function e(){var r,n,i,a=this;return regeneratorRuntime.wrap((function(e){for(;;)switch(e.prev=e.next){case 0:if(!(this.array.length<1)){e.next=2;break}return e.abrupt("return");case 2:r=this.array,n=new t((function(t,e){return a.compare(r[t],r[e])}),[0]);case 4:if(!((i=n.pop())0){e.next=4;break}case 12:case"end":return e.stop()}}),e,this)}))},{key:"update",value:function(t,e){var r=this.array.indexOf(t);return!(r<0||(this.array[r]=e,(0,a.AV)(r,this.compare,this.array),(0,a.$f)(r,this.compare,this.array),0))}}])&&l(e.prototype,r),t}()},143:()=>{},856:(t,e,r)=>{"use strict";r.r(e),r.d(e,{BinaryHeap:()=>n.L,SkewHeap:()=>o.R});var n=r(352),i=r(143),a={};for(const t in i)["default","BinaryHeap"].indexOf(t)<0&&(a[t]=()=>i[t]);r.d(e,a);var o=r(903)},903:(t,e,r)=>{"use strict";r.d(e,{R:()=>p});var n=r(150),i=regeneratorRuntime.mark(u);function a(t){if(null!=t){var e=Object.assign({},t),r=new n._([e]);do{(t=r.pop()).left?r.push(t.left=Object.assign({},t.left)):t.right&&r.push(t.right=Object.assign({},t.right))}while(r.size>0);return e}}function o(t){if(!(null==t||t.length<1)){var e=t.length,r=new Array(e);r[0]={value:t[0]};for(var n=1;n>>1],a={value:t[n]};r[n]=a,1&n?i.left=a:i.right=a}return r[0]}}function u(t){var e;return regeneratorRuntime.wrap((function(r){for(;;)switch(r.prev=r.next){case 0:e=new n._([t]);case 1:if(null==(t=e.pop())){r.next=7;break}return r.next=5,t;case 5:e.push(t.right),e.push(t.left);case 7:if(e.size>0){r.next=1;break}case 8:case"end":return r.stop()}}),i)}var l,s=r(352),h=r(565);function f(t,e){var r="undefined"!=typeof Symbol&&t[Symbol.iterator]||t["@@iterator"];if(!r){if(Array.isArray(t)||(r=function(t,e){if(t){if("string"==typeof t)return c(t,e);var r=Object.prototype.toString.call(t).slice(8,-1);return"Object"===r&&t.constructor&&(r=t.constructor.name),"Map"===r||"Set"===r?Array.from(t):"Arguments"===r||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(r)?c(t,e):void 0}}(t))||e&&t&&"number"==typeof t.length){r&&(t=r);var n=0,i=function(){};return{s:i,n:function(){return n>=t.length?{done:!0}:{done:!1,value:t[n++]}},e:function(t){throw t},f:i}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}var a,o=!0,u=!1;return{s:function(){r=r.call(t)},n:function(){var t=r.next();return o=t.done,t},e:function(t){u=!0,a=t},f:function(){try{o||null==r.return||r.return()}finally{if(u)throw a}}}}function c(t,e){(null==e||e>t.length)&&(e=t.length);for(var r=0,n=new Array(e);r0){e.next=3;break}case 9:case"end":return e.stop()}}),e,this)}))},{key:"update",value:function(t,e){if(null==this.root)return!1;if(this.root.value===t)return this.root=(0,h.pC)(this.compare,[this.root.left,this.root.right,{value:e}]),!0;var r,n=f(u(this.root));try{for(n.s();!(r=n.n()).done;){var i=r.value,a=i.left&&i.left.value===t?"left":i.right&&i.right.value===t?"right":void 0;if(null!=a){var o=i[a];return i[a]=void 0,this.root=(0,h.pC)(this.compare,[this.root,o.left,o.right,{value:e}]),!0}}}catch(t){n.e(t)}finally{n.f()}return!1}}])&&v(e.prototype,r),t}()},565:(t,e,r)=>{"use strict";r.d(e,{$f:()=>o,g3:()=>u,AV:()=>l,pC:()=>s});var n=r(148);function i(t,e){var r="undefined"!=typeof Symbol&&t[Symbol.iterator]||t["@@iterator"];if(!r){if(Array.isArray(t)||(r=function(t,e){if(t){if("string"==typeof t)return a(t,e);var r=Object.prototype.toString.call(t).slice(8,-1);return"Object"===r&&t.constructor&&(r=t.constructor.name),"Map"===r||"Set"===r?Array.from(t):"Arguments"===r||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(r)?a(t,e):void 0}}(t))||e&&t&&"number"==typeof t.length){r&&(t=r);var n=0,i=function(){};return{s:i,n:function(){return n>=t.length?{done:!0}:{done:!1,value:t[n++]}},e:function(t){throw t},f:i}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}var o,u=!0,l=!1;return{s:function(){r=r.call(t)},n:function(){var t=r.next();return u=t.done,t},e:function(t){l=!0,o=t},f:function(){try{u||null==r.return||r.return()}finally{if(l)throw o}}}}function a(t,e){(null==e||e>t.length)&&(e=t.length);for(var r=0,n=new Array(e);r0;){var i=Math.floor((t+1)/2)-1,a=r[i];if(e(a,n)<=0)break;r[i]=n,r[t]=a,t=i}}function u(t,e){for(var r=e.length+1>>>1;r>0;l(--r,t,e));}function l(t,e,r){for(var n=r.length,i=r[t];;){var a=2*t+1;if(a>=n)break;var o=r[a];if(a+10);return f}},125:(t,e,r)=>{"use strict";r.d(e,{S:()=>h});var n,i=r(678);function a(t){return function(t){if(Array.isArray(t))return l(t)}(t)||function(t){if("undefined"!=typeof Symbol&&null!=t[Symbol.iterator]||null!=t["@@iterator"])return Array.from(t)}(t)||u(t)||function(){throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}()}function o(t,e){var r="undefined"!=typeof Symbol&&t[Symbol.iterator]||t["@@iterator"];if(!r){if(Array.isArray(t)||(r=u(t))||e&&t&&"number"==typeof t.length){r&&(t=r);var n=0,i=function(){};return{s:i,n:function(){return n>=t.length?{done:!0}:{done:!1,value:t[n++]}},e:function(t){throw t},f:i}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}var a,o=!0,l=!1;return{s:function(){r=r.call(t)},n:function(){var t=r.next();return o=t.done,t},e:function(t){l=!0,a=t},f:function(){try{o||null==r.return||r.return()}finally{if(l)throw a}}}}function u(t,e){if(t){if("string"==typeof t)return l(t,e);var r=Object.prototype.toString.call(t).slice(8,-1);return"Object"===r&&t.constructor&&(r=t.constructor.name),"Map"===r||"Set"===r?Array.from(t):"Arguments"===r||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(r)?l(t,e):void 0}}function l(t,e){(null==e||e>t.length)&&(e=t.length);for(var r=0,n=new Array(e);r=0&&t<=this.size&&this.array.splice(t,0,e),this.size}},{key:"addAll",value:function(t,e){if(t>=0&&t<=this.size){var r,n=o((0,i.dC)(1e4,e));try{for(n.s();!(r=n.n()).done;){var u,l=r.value;(u=this.array).splice.apply(u,[t,0].concat(a(l))),t+=l.length}}catch(t){n.e(t)}finally{n.f()}}return this.size}},{key:"clear",value:function(){this.array.length=0}},{key:"concat",value:function(){for(var e=new t(this),r=arguments.length,n=new Array(r),i=0;i=this.size?void 0:this.array[t]}},{key:"getSet",value:function(t,e){var r=void 0;return t>=0&&t=this.size?void 0:this.array.splice(t,1)[0]}},{key:"reverse",value:function(t,e){var r,n;for(t=(0,i.CQ)(null!==(r=t)&&void 0!==r?r:0,0,this.size),e=(0,i.CQ)(null!==(n=e)&&void 0!==n?n:this.size,0,this.size)-1;t=0&&t=0?function(){return Math.min(r,o.size)}:function(){return o.size+r};case 2:if(!(e{"use strict";r.d(e,{s:()=>s});var n,i=r(678);function a(t,e){if(t){if("string"==typeof t)return o(t,e);var r=Object.prototype.toString.call(t).slice(8,-1);return"Object"===r&&t.constructor&&(r=t.constructor.name),"Map"===r||"Set"===r?Array.from(t):"Arguments"===r||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(r)?o(t,e):void 0}}function o(t,e){(null==e||e>t.length)&&(e=t.length);for(var r=0,n=new Array(e);rthis.length)return this.length;var r=this._get(t-1),n={next:r.next,prev:r,value:e};return r.next=n,n.next.prev=n,++this.length}},{key:"addAll",value:function(t,e){return t>=0&&t<=this.length&&this._addAll(this._get(t),e),this.length}},{key:"clear",value:function(){this.length=0,this.root.prev=this.root.next=this.root}},{key:"concat",value:function(){for(var e=new t(this),r=arguments.length,n=new Array(r),i=0;i=(r=e+Math.min(r-e,this.length-t)))return this;if(e=this.length?void 0:this._get(t).value}},{key:"getSet",value:function(t,e){if(!(t<0||t>=this.length)){var r=this._get(t),n=r.value;return r.value=e(r.value),n}}},{key:"pop",value:function(){if(!(this.length<1)){var t=this.root.prev;return t.prev.next=this.root,this.root.prev=t.prev,--this.length,t.value}}},{key:"push",value:function(t){var e=this.root.prev,r={next:this.root,prev:e,value:t};return e.next=this.root.prev=r,++this.length}},{key:"remove",value:function(t){if(!(t<0||t>=this.length)){var e=this._get(t);return e.prev.next=e.next,e.next.prev=e.prev,--this.length,e.value}}},{key:"reverse",value:function(t,e){var r,n;if(t=(0,i.CQ)(null!==(r=t)&&void 0!==r?r:0,0,this.length),(e=(0,i.CQ)(null!==(n=e)&&void 0!==n?n:this.length,0,this.length))-t<2)return this;var a=this._get(t-1),o=a.next,u=o;do{var l=u.next;u.next=u.prev,u.prev=l,a.next=u,u=l}while(++t=this.length)){var r=this._get(t),n=r.value;return r.value=e,n}}},{key:"shift",value:function(){if(!(this.length<1)){var t=this.root.next;return t.next.prev=this.root,this.root.next=t.next,--this.length,t.value}}},{key:"size",get:function(){return this.length}},{key:"slice",value:function(e,r){return new t(this.view(e,r))}},{key:"splice",value:function(e,r,n){var a,o;e=(0,i.CQ)(null!==(a=e)&&void 0!==a?a:0,0,this.size),r=(0,i.uZ)(null!==(o=r)&&void 0!==o?o:this.size,0,this.size-e);var u=new t;if(null==n&&r<1)return u;for(var l=this._get(e);r-- >0;)u.push(l.value),l.prev.next=l.next,l.next.prev=l.prev,l=l.next,--this.length;return this._addAll(l,null!=n?n:[]),u}},{key:"sort",value:function(t){if(this.length>1){var e=(o=(0,i.qt)(this.root.next,this.length,!0,t),u=2,function(t){if(Array.isArray(t))return t}(o)||function(t,e){var r=t&&("undefined"!=typeof Symbol&&t[Symbol.iterator]||t["@@iterator"]);if(null!=r){var n,i,a=[],o=!0,u=!1;try{for(r=r.call(t);!(o=(n=r.next()).done)&&(a.push(n.value),!e||a.length!==e);o=!0);}catch(t){u=!0,i=t}finally{try{o||null==r.return||r.return()}finally{if(u)throw i}}return a}}(o,u)||a(o,u)||function(){throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}()),r=e[0],n=e[1];this.root.next=r,n.next.prev=n}var o,u;return this}},{key:n,value:regeneratorRuntime.mark((function t(){var e;return regeneratorRuntime.wrap((function(t){for(;;)switch(t.prev=t.next){case 0:e=this.root.next;case 1:if(e===this.root){t.next=7;break}return t.next=4,e.value;case 4:e=e.next,t.next=1;break;case 7:case"end":return t.stop()}}),t,this)}))},{key:"unshift",value:function(t){var e=this.root.next,r={next:e,prev:this.root,value:t};return this.root.next=e.prev=r,++this.length}},{key:"update",value:function(t,e,r){var n,a;if(null==r&&(arguments.length<2?(r=t,t=void 0):(r=e,e=void 0)),(t=(0,i.CQ)(null!==(n=t)&&void 0!==n?n:0,0,this.length))<(e=(0,i.CQ)(null!==(a=e)&&void 0!==a?a:this.length,0,this.length))){var o=this._get(t);do{o.value=r(o.value,t),o=o.next}while(++t=0?function(){return r}:function(){return u.length+r})())){t.next=8;break}o=this._get(e);case 4:return t.next=6,o.value;case 6:o=o.next;case 7:if(++e=t.length?{done:!0}:{done:!1,value:t[n++]}},e:function(t){throw t},f:i}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}var o,u=!0,l=!1;return{s:function(){r=r.call(t)},n:function(){var t=r.next();return u=t.done,t},e:function(t){l=!0,o=t},f:function(){try{u||null==r.return||r.return()}finally{if(l)throw o}}}}(e);try{for(i.s();!(r=i.n()).done;){var o={prev:n,value:r.value};n.next=o,n=o,++this.length}}catch(t){i.e(t)}finally{i.f()}n.next=t,t.prev=n}},{key:"_get",value:function(t){var e=this.root;if(t=0;)e=e.next;else for(t=this.length-t;t>0;--t)e=e.prev;return e}}])&&u(e.prototype,r),t}()},372:(t,e,r)=>{"use strict";r.r(e),r.d(e,{ArrayList:()=>n.S,DoublyLinkedList:()=>i.s,LinkedList:()=>a.S});var n=r(125),i=r(736),a=r(148),o=r(241),u={};for(const t in o)["default","ArrayList","DoublyLinkedList","LinkedList"].indexOf(t)<0&&(u[t]=()=>o[t]);r.d(e,u)},148:(t,e,r)=>{"use strict";r.d(e,{S:()=>s});var n,i=r(678);function a(t,e){if(t){if("string"==typeof t)return o(t,e);var r=Object.prototype.toString.call(t).slice(8,-1);return"Object"===r&&t.constructor&&(r=t.constructor.name),"Map"===r||"Set"===r?Array.from(t):"Arguments"===r||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(r)?o(t,e):void 0}}function o(t,e){(null==e||e>t.length)&&(e=t.length);for(var r=0,n=new Array(e);r=0&&t=0&&t=(r=e+Math.min(r-e,this.length-t)))return this;if(tr){var u=this._get(e-1);return this._copyWithin(u,this._get(t-e-1,u),r-e),this}var l=this._get(e-1),s=this._get(r-e-1,l),h=this._copyWithin(l,s,t-e);t+(r-e)>=this.length&&(this.tail=s);var f=l.next;return l.next=s.next,s.next=h.next,h.next=f,this}},{key:"fill",value:function(t,e,r){var n,a;if((e=(0,i.CQ)(null!==(n=e)&&void 0!==n?n:0,0,this.length))<(r=(0,i.CQ)(null!==(a=r)&&void 0!==a?a:this.length,0,this.length))){var o=this._get(e);do{o.value=t,o=o.next}while(++e=this.length))return t=this.length)){var r=t=this.length)){var e=this._get(t-1),r=e.next;return e.next=r.next,t===--this.length&&(this.tail=e),r.value}}},{key:"reverse",value:function(t,e){var r,n;if(t=(0,i.CQ)(null!==(r=t)&&void 0!==r?r:0,0,this.length),(e=(0,i.CQ)(null!==(n=e)&&void 0!==n?n:this.length,0,this.length))-t<2)return this;var a=this._get(t-1);this.tail=e>=this.length?a.next:this.tail;for(var o=a.next,u=o,l=o.next;++t=this.length)){var r=this._get(t),n=r.value;return r.value=e,n}}},{key:"shift",value:function(){return this.remove(0)}},{key:"size",get:function(){return this.length}},{key:"slice",value:function(e,r){return new t(this.view(e,r))}},{key:"splice",value:function(e,r,n){var a,o;e=(0,i.CQ)(null!==(a=e)&&void 0!==a?a:0,0,this.size),r=(0,i.uZ)(null!==(o=r)&&void 0!==o?o:this.size,0,this.size-e);var u=new t;if(null==n&&r<1)return u;for(var l=this._get(e-1),s=e+r>=this.size;r-- >0;){var h=l.next;u.push(h.value),l.next=h.next,--this.length}return l=this._addAll(l,null!=n?n:[]),this.tail=s?l:this.tail,u}},{key:"sort",value:function(t){if(this.length>1){var e=(o=(0,i.qt)(this.root.next,this.length,!1,t),u=2,function(t){if(Array.isArray(t))return t}(o)||function(t,e){var r=t&&("undefined"!=typeof Symbol&&t[Symbol.iterator]||t["@@iterator"]);if(null!=r){var n,i,a=[],o=!0,u=!1;try{for(r=r.call(t);!(o=(n=r.next()).done)&&(a.push(n.value),!e||a.length!==e);o=!0);}catch(t){u=!0,i=t}finally{try{o||null==r.return||r.return()}finally{if(u)throw i}}return a}}(o,u)||a(o,u)||function(){throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}()),r=e[0],n=e[1];this.root.next=r,this.tail=n}var o,u;return this}},{key:n,value:regeneratorRuntime.mark((function t(){var e;return regeneratorRuntime.wrap((function(t){for(;;)switch(t.prev=t.next){case 0:e=this.root.next;case 1:if(e===this.root){t.next=7;break}return t.next=4,e.value;case 4:e=e.next,t.next=1;break;case 7:case"end":return t.stop()}}),t,this)}))},{key:"unshift",value:function(t){return this.add(0,t)}},{key:"update",value:function(t,e,r){var n,a;if(null==r&&(arguments.length<2?(r=t,t=void 0):(r=e,e=void 0)),(t=(0,i.CQ)(null!==(n=t)&&void 0!==n?n:0,0,this.length))<(e=(0,i.CQ)(null!==(a=e)&&void 0!==a?a:this.length,0,this.length))){var o=this._get(t);do{o.value=r(o.value,t),o=o.next}while(++t=0?function(){return r}:function(){return u.length+r})())){t.next=8;break}o=this._get(e);case 4:return t.next=6,o.value;case 6:o=o.next;case 7:if(++e=t.length?{done:!0}:{done:!1,value:t[n++]}},e:function(t){throw t},f:i}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}var o,u=!0,l=!1;return{s:function(){r=r.call(t)},n:function(){var t=r.next();return u=t.done,t},e:function(t){l=!0,o=t},f:function(){try{u||null==r.return||r.return()}finally{if(l)throw o}}}}(e);try{for(i.s();!(r=i.n()).done;){var o={value:r.value};t.next=o,t=o,++this.length}}catch(t){i.e(t)}finally{i.f()}return t.next=n,t}},{key:"_copyWithin",value:function(t,e,r){for(;r-- >0;)t=t.next,(e=e.next).value=t.value;return e}},{key:"_get",value:function(t){for(var e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:this.root,r=e;t-- >=0;)r=r.next;return r}}])&&u(e.prototype,r),t}()},241:()=>{},678:(t,e,r)=>{"use strict";r.d(e,{dC:()=>o,uZ:()=>u,CQ:()=>l,qt:()=>s});var n=regeneratorRuntime.mark(o);function i(t,e){var r="undefined"!=typeof Symbol&&t[Symbol.iterator]||t["@@iterator"];if(!r){if(Array.isArray(t)||(r=function(t,e){if(t){if("string"==typeof t)return a(t,e);var r=Object.prototype.toString.call(t).slice(8,-1);return"Object"===r&&t.constructor&&(r=t.constructor.name),"Map"===r||"Set"===r?Array.from(t):"Arguments"===r||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(r)?a(t,e):void 0}}(t))||e&&t&&"number"==typeof t.length){r&&(t=r);var n=0,i=function(){};return{s:i,n:function(){return n>=t.length?{done:!0}:{done:!1,value:t[n++]}},e:function(t){throw t},f:i}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}var o,u=!0,l=!1;return{s:function(){r=r.call(t)},n:function(){var t=r.next();return u=t.done,t},e:function(t){l=!0,o=t},f:function(){try{u||null==r.return||r.return()}finally{if(l)throw o}}}}function a(t,e){(null==e||e>t.length)&&(e=t.length);for(var r=0,n=new Array(e);r=t)){n.next=20;break}return n.next=9,r;case 9:if(n.t1=l=n.sent,n.t0=null!==n.t1,!n.t0){n.next=13;break}n.t0=void 0!==l;case 13:if(!n.t0){n.next=17;break}n.t2=l,n.next=18;break;case 17:n.t2=t;case 18:t=n.t2,r=[];case 20:n.next=4;break;case 22:n.next=27;break;case 24:n.prev=24,n.t3=n.catch(2),a.e(n.t3);case 27:return n.prev=27,a.f(),n.finish(27);case 30:if(!(r.length>0)){n.next=33;break}return n.next=33,r;case 33:case"end":return n.stop()}}),n,null,[[2,24,27,30]])}function u(t,e,r){return Math.min(r,Math.max(e,t))}function l(t,e,r){return u(function(t,e){return t<0?e+t:t}(t,r),e,r)}function s(t,e,r,n){if(e<2)return[t,t];e/=2;var i=[Math.ceil(e),Math.floor(e)],a=s(t,i[0],r,n),o=s(a[1].next,i[1],r,n);t=a[1],a[1]=o[0],o[0]=t,o[0].next=o[1].next;var u=a[0].prev;return t=function(t,e,r,n){var i={},a=i;do{var o=+(n(t[0].value,t[1].value)>0);a.next=t[o],r&&(a.next.prev=a),a=a.next,t[o]=a.next,--e[o]}while(e[0]>0&&e[1]>0);return a.next=t[+(e[0]<1)],r&&a.next&&(a.next.prev=a),i.next}(a,i,r,n),r&&(t.prev=u),[t,o[+(i[0]<1)]]}},451:(t,e,r)=>{"use strict";var n;function i(t,e){for(var r=0;ra}),n=Symbol.iterator;var a=function(){function t(e){var r,n;!function(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}(this,t),n=void 0,(r="array")in this?Object.defineProperty(this,r,{value:n,enumerable:!0,configurable:!0,writable:!0}):this[r]=n,this.array=e?Array.from(e):[]}var e,r;return e=t,(r=[{key:"clear",value:function(){this.array.length=0}},{key:"dequeue",value:function(){return this.size<1?void 0:this.array.shift()}},{key:"enqueue",value:function(t){return this.array.push(t)}},{key:"peek",value:function(){return this.size<1?void 0:this.array[0]}},{key:"size",get:function(){return this.array.length}},{key:n,value:function(){return this.array[Symbol.iterator]()}}])&&i(e.prototype,r),t}()},753:(t,e,r)=>{"use strict";r.r(e),r.d(e,{ArrayQueue:()=>n.H,LinkedQueue:()=>i.S});var n=r(451),i=r(519),a=r(786),o={};for(const t in a)["default","ArrayQueue","LinkedQueue"].indexOf(t)<0&&(o[t]=()=>a[t]);r.d(e,o)},519:(t,e,r)=>{"use strict";r.d(e,{S:()=>o});var n,i=r(148);function a(t,e){for(var r=0;r{},909:(t,e,r)=>{"use strict";var n;function i(t,e){for(var r=0;ra}),n=Symbol.iterator;var a=function(){function t(e){var r,n;!function(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}(this,t),n=void 0,(r="array")in this?Object.defineProperty(this,r,{value:n,enumerable:!0,configurable:!0,writable:!0}):this[r]=n,this.array=e?Array.from(e):[]}var e,r;return e=t,(r=[{key:"clear",value:function(){this.array.length=0}},{key:"peek",value:function(){return this.array[this.array.length-1]}},{key:"pop",value:function(){return this.array.pop()}},{key:"push",value:function(t){return this.array.push(t)}},{key:"size",get:function(){return this.array.length}},{key:n,value:regeneratorRuntime.mark((function t(){var e,r;return regeneratorRuntime.wrap((function(t){for(;;)switch(t.prev=t.next){case 0:e=this.array,r=e.length;case 2:if(!(r>0)){t.next=7;break}case 3:return t.next=5,e[--r];case 5:t.next=2;break;case 7:case"end":return t.stop()}}),t,this)}))}])&&i(e.prototype,r),t}()},610:(t,e,r)=>{"use strict";r.r(e),r.d(e,{ArrayStack:()=>n.O,LinkedStack:()=>i._});var n=r(909),i=r(150),a=r(173),o={};for(const t in a)["default","ArrayStack","LinkedStack"].indexOf(t)<0&&(o[t]=()=>a[t]);r.d(e,o)},150:(t,e,r)=>{"use strict";r.d(e,{_:()=>u});var n,i=r(148);function a(t,e){(null==e||e>t.length)&&(e=t.length);for(var r=0,n=new Array(e);r=t.length?{done:!0}:{done:!1,value:t[n++]}},e:function(t){throw t},f:i}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}var o,u=!0,l=!1;return{s:function(){r=r.call(t)},n:function(){var t=r.next();return u=t.done,t},e:function(t){l=!0,o=t},f:function(){try{u||null==r.return||r.return()}finally{if(l)throw o}}}}(e||[]);try{for(u.s();!(o=u.n()).done;){var l=o.value;this.push(l)}}catch(t){u.e(t)}finally{u.f()}}var e,r;return e=t,(r=[{key:"clear",value:function(){this.list.clear()}},{key:"peek",value:function(){return this.list.get(0)}},{key:"pop",value:function(){return this.list.shift()}},{key:"push",value:function(t){return this.list.unshift(t)}},{key:"size",get:function(){return this.list.size}},{key:n,value:function(){return this.list[Symbol.iterator]()}}])&&o(e.prototype,r),t}()},173:()=>{}},e={};function r(n){var i=e[n];if(void 0!==i)return i.exports;var a=e[n]={exports:{}};return t[n](a,a.exports,r),a.exports}r.n=t=>{var e=t&&t.__esModule?()=>t.default:()=>t;return r.d(e,{a:e}),e},r.d=(t,e)=>{for(var n in e)r.o(e,n)&&!r.o(t,n)&&Object.defineProperty(t,n,{enumerable:!0,get:e[n]})},r.o=(t,e)=>Object.prototype.hasOwnProperty.call(t,e),r.r=t=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(t,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(t,"__esModule",{value:!0})};var n={};return(()=>{"use strict";r.r(n);var t=r(856),e={};for(const r in t)"default"!==r&&(e[r]=()=>t[r]);r.d(n,e);var i=r(372);e={};for(const t in i)["default","BinaryHeap","SkewHeap"].indexOf(t)<0&&(e[t]=()=>i[t]);r.d(n,e);var a=r(753);e={};for(const t in a)["default","BinaryHeap","SkewHeap","ArrayList","DoublyLinkedList","LinkedList"].indexOf(t)<0&&(e[t]=()=>a[t]);r.d(n,e);var o=r(610);e={};for(const t in o)["default","BinaryHeap","SkewHeap","ArrayList","DoublyLinkedList","LinkedList","ArrayQueue","LinkedQueue"].indexOf(t)<0&&(e[t]=()=>o[t]);r.d(n,e)})(),n})()})); //# sourceMappingURL=dastal.min.js.map \ No newline at end of file diff --git a/dist/dastal.min.js.map b/dist/dastal.min.js.map index 66d2143..423ae4a 100644 --- a/dist/dastal.min.js.map +++ b/dist/dastal.min.js.map @@ -1 +1 @@ -{"version":3,"sources":["webpack://Dastal/webpack/universalModuleDefinition","webpack://Dastal/./src/list/arrayList.ts","webpack://Dastal/./src/list/doublyLinkedList.ts","webpack://Dastal/./src/list/linkedList.ts","webpack://Dastal/./src/queue/arrayQueue.ts","webpack://Dastal/./src/queue/linkedQueue.ts","webpack://Dastal/./src/stack/arrayStack.ts","webpack://Dastal/./src/stack/linkedStack.ts","webpack://Dastal/./src/utils.ts","webpack://Dastal/webpack/bootstrap","webpack://Dastal/webpack/runtime/compat get default export","webpack://Dastal/webpack/runtime/define property getters","webpack://Dastal/webpack/runtime/hasOwnProperty shorthand","webpack://Dastal/webpack/runtime/make namespace object"],"names":["root","factory","exports","module","define","amd","self","Symbol","iterator","ArrayList","elements","this","array","Array","from","index","element","size","splice","batch","items","length","out","lists","list","addAll","min","max","wrap","copyWithin","fill","undefined","callback","value","pop","push","temp","prev","shift","slice","start","count","clamp","unshift","arguments","len","Math","DoublyLinkedList","next","_addAll","_get","node","nodeA","nodeB","tail","head","view","LinkedList","_copyWithin","nodeC","nodeD","remove","deleted","newTail","add","to","ArrayQueue","LinkedQueue","clear","get","ArrayStack","i","LinkedStack","f","num","__webpack_module_cache__","__webpack_require__","moduleId","cachedModule","__webpack_modules__","n","getter","__esModule","d","a","definition","key","o","Object","defineProperty","enumerable","obj","prop","prototype","hasOwnProperty","call","r","toStringTag"],"mappings":"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","file":"dastal.min.js","sourcesContent":["(function webpackUniversalModuleDefinition(root, factory) {\n\tif(typeof exports === 'object' && typeof module === 'object')\n\t\tmodule.exports = factory();\n\telse if(typeof define === 'function' && define.amd)\n\t\tdefine(\"Dastal\", [], factory);\n\telse if(typeof exports === 'object')\n\t\texports[\"Dastal\"] = factory();\n\telse\n\t\troot[\"Dastal\"] = factory();\n})(self, function() {\nreturn ","import { List } from './list';\nimport { batch, clamp, wrap } from '../utils';\n\n/**\n * An implementation of the {@link List} interface using an array\n */\nexport class ArrayList implements List {\n /**\n * @ignore\n */\n protected array: Array;\n\n constructor(elements?: Iterable) {\n this.array = elements ? Array.from(elements) : [];\n }\n /**\n * Add the element at the specified index.\n *\n * @param index - The index to add into\n * @param element - The element to add\n *\n * @returns The new size of the list\n */\n add(index: number, element: T): number {\n if (index >= 0 && index <= this.size) {\n this.array.splice(index, 0, element);\n }\n return this.size;\n }\n /**\n * Add elements at the specified index.\n *\n * @param index - The index to add into\n * @param element - The elements to add\n *\n * @returns The new size of the list\n */\n addAll(index: number, elements: Iterable): number {\n if (index >= 0 && index <= this.size) {\n for (const items of batch(10000, elements)) {\n this.array.splice(index, 0, ...items);\n index += items.length;\n }\n }\n return this.size;\n }\n /**\n * Removes all elements\n */\n clear(): void {\n this.array.length = 0;\n }\n /**\n * Combines the list with multiple iterables into a new list.\n * Does not modify the existing list or inputs.\n *\n * @param lists — Additional iterables to add to the end of the list.\n *\n * @returns A new list consisting of the elements in the list on which\n * it is called, followed in order by the elements of each argument. It\n * does not recurse into nested iterable arguments\n */\n concat(...lists: Iterable[]): ArrayList {\n const out = new ArrayList(this);\n for (const list of lists) {\n out.addAll(out.size, list);\n }\n return out;\n }\n /**\n * Copies a section of the list identified by min and max to the same array at position index.\n *\n * Negative indices can be used for index, min and max to indicate an offset from the\n * end of the list. For example, -2 refers to the second to last element of the list.\n *\n * Note that this method will not change the size of the list. If index is after min,\n * the copied sequence will be trimmed to fit list.size\n *\n * @param index - Where to copy the sequence to\n * @param min - Where to start copying elements from, inclusive. Defaults to 0\n * @param max - Where to end copying elements from, exclusive. Defaults to list.size\n *\n * @returns The list\n */\n copyWithin(index: number, min?: number, max?: number): this {\n index = wrap(index ?? 0, 0, this.size);\n min = wrap(min ?? 0, 0, this.size);\n max = wrap(max ?? this.size, 0, this.size);\n this.array.copyWithin(index, min, max);\n return this;\n }\n /**\n * Returns the this object after filling the section identified by min and max with element.\n *\n * Negative indices can be used for min and max to indicate an offset from the\n * end of the list. For example, -2 refers to the second to last element of the list.\n *\n * @param element — element to fill list section with\n * @param min - Where to start filling the list, inclusive. Defaults to 0\n * @param end - Where to stop filling the list, exclusive. Defaults to list.size\n *\n * @returns The list on which this method was called\n */\n fill(element: T, min?: number, max?: number): this {\n min = wrap(min ?? 0, 0, this.size);\n max = wrap(max ?? this.size, 0, this.size);\n this.array.fill(element, min, max);\n return this;\n }\n /**\n * Return the element at the specified index.\n *\n * A negative index can be used for to indicate an offset from the\n * end of the list. For example, -2 refers to the second to last element of the list.\n *\n * @param index - The index to retrieve\n *\n * @returns The element at the index, or `undefined` if index is invalid\n */\n get(index: number): T | undefined {\n return index < 0 || index >= this.size ? undefined : this.array[index];\n }\n /**\n * Update the element at the specified index.\n *\n * A negative index can be used to indicate an offset from the\n * end of the list. For example, -2 refers to the second to last element of the list.\n *\n * @param index - The index to retrieve\n * @param callback - A function that receives the previous element and returns\n * the new element. The function is only called if the index is valid\n *\n * @returns The previous element at the index, or `undefined` if index is invalid\n */\n getSet(index: number, callback: (element: T) => T): T | undefined {\n let value: T | undefined = undefined;\n if (index >= 0 && index < this.size) {\n value = this.array[index];\n this.array[index] = callback(value);\n }\n return value;\n }\n /**\n * Retrieves and removes the end of the list\n *\n * @returns The element at the end of the list, or `undefined` if empty.\n */\n pop(): T | undefined {\n return this.array.pop();\n }\n /**\n * Inserts the specified element into the end of the list\n *\n * @param element - The element to be inserted\n *\n * @returns The new size of the list\n */\n push(element: T): number {\n return this.array.push(element);\n }\n /**\n * Retrieves and removes the element at the given index.\n *\n * A negative index can be used to indicate an offset from the\n * end of the list. For example, -2 refers to the second to last element of the list.\n *\n * @param index - The index to remove\n *\n * @returns The value at the index, or `undefined` if the index is invalid\n */\n remove(index: number): T | undefined {\n return index < 0 || index >= this.size ? undefined : this.array.splice(index, 1)[0];\n }\n /**\n * Reverses the elements in the list in place.\n *\n * Negative indices can be used for min and max to indicate an offset from the\n * end of the list. For example, -2 refers to the second to last element of the list.\n *\n * @param min - The beginning index of the specified portion of the list, inclusive. Defaults to 0\n * @param max - The end index of the specified portion of the list, exclusive. Defaults to list.size\n *\n * @returns a reference to the same list\n */\n reverse(min?: number, max?: number): this {\n min = wrap(min ?? 0, 0, this.size);\n max = wrap(max ?? this.size, 0, this.size) - 1;\n while (min < max) {\n const temp = this.array[min];\n this.array[min++] = this.array[max];\n this.array[max--] = temp;\n }\n return this;\n }\n /**\n * Update the element at the specified index.\n *\n * @param index - The index to retrieve\n * @param element - The new element to insert at index\n *\n * @returns The previous element in the index, or undefined if the index is invalid\n */\n set(index: number, element: T): T | undefined {\n let prev: T | undefined = undefined;\n if (index >= 0 && index < this.size) {\n prev = this.array[index];\n this.array[index] = element;\n }\n return prev;\n }\n /**\n * Retrieves and removes the first element in the list\n *\n * @returns The element at the front of the list or `undefined` if this list is empty.\n */\n shift(): T | undefined {\n return this.array.shift();\n }\n /**\n * The number of elements in this list\n */\n get size(): number {\n return this.array.length;\n }\n /**\n * Returns a copy of a section of the list.\n *\n * Negative indices can be used for min and max to indicate an offset from the\n * end of the list. For example, -2 refers to the second to last element of the list.\n *\n * @param min - The beginning index of the specified portion of the list, inclusive. Defaults to 0\n * @param max - The end index of the specified portion of the list, exclusive. Defaults to list.size\n *\n * @returns A new list with a copy of the indicated section of the original list\n */\n slice(min?: number, max?: number): ArrayList {\n return new ArrayList(this.array.slice(min, max));\n }\n /**\n * Removes elements from the list and optionally inserts new elements in their place.\n * Returns any deleted elements.\n *\n * @param start - The index from which to start removing elements. Defaults to 0\n *\n * If > size, start will be set to size. In this case, no element will be\n * deleted but the method can still add elements to the end of the list.\n *\n * If < 0, start will indicate an offset from the end of the list. For example,\n * -2 refers to the second to last element of the list.\n *\n * If < -size, start will be set to 0\n * @param count - The number of elements to remove. Defaults to size - start\n *\n * If >= size - start (that is, if it's >= than the number of elements from start\n * until the end of the list), then all the elements from start until the end of\n * the list will be removed.\n *\n * If <= 0, no elements are removed\n * @param elements - The new elements to insert at start. Defaults to none\n *\n * @returns A new list of deleted elements\n */\n splice(start?: number, count?: number, elements?: Iterable): List {\n start = wrap(start ?? 0, 0, this.size);\n count = clamp(count ?? this.size, 0, this.size - start);\n const list = new ArrayList(this.array.splice(start, count));\n for (const items of batch(10000, elements ?? [])) {\n this.array.splice(start, 0, ...items);\n start += items.length;\n }\n return list;\n }\n /**\n * Receive an iterator through the list.\n *\n * **Note:** Unexpected behavior can occur if the collection is modified during iteration.\n *\n * @returns An iterator through the list\n */\n [Symbol.iterator](): Iterator {\n return this.array[Symbol.iterator]();\n }\n /**\n * Inserts the specified element into the front of the list\n *\n * @param element - The element to be inserted\n *\n * @returns The new size of the list\n */\n unshift(element: T): number {\n return this.array.unshift(element);\n }\n /**\n * Update the elements of the list\n *\n * @param callback - A function called for each index. Returns the new element\n *\n * @returns The list on which this method was called\n */\n update(callback: (element: T, index: number) => T): this;\n /**\n * Update the elements of the list\n *\n * Negative indices can be used to indicate an offset from the\n * end of the list. For example, -2 refers to the second to last element of the list.\n *\n * @param min - Where to start filling the list, inclusive. Defaults to 0\n * @param callback - A function called for each index. Returns the new element\n *\n * @returns The list on which this method was called\n */\n update(min: number | undefined, callback: (element: T, index: number) => T): this;\n /**\n * Update the elements of the list\n *\n * Negative indices can be used for min and max to indicate an offset from the\n * end of the list. For example, -2 refers to the second to last element of the list.\n *\n * @param min - Where to start filling the list, inclusive. Defaults to 0\n * @param max - Where to stop filling the list, exclusive. Defaults to list.size\n * @param callback - A function called for each index. Returns the new element\n *\n * @returns The list on which this method was called\n */\n update(\n min: number | undefined,\n max: number | undefined,\n callback: (element: T, index: number) => T,\n ): this;\n update(\n min: number | undefined | ((element: T, index: number) => T),\n max?: number | ((element: T, index: number) => T),\n callback?: (element: T, index: number) => T,\n ): this {\n if (callback == null) {\n if (arguments.length < 2) {\n callback = min as (element: T, index: number) => T;\n min = undefined;\n } else {\n callback = max as (element: T, index: number) => T;\n max = undefined;\n }\n }\n min = wrap((min as number) ?? 0, 0, this.size);\n max = wrap((max as number) ?? this.size, 0, this.size);\n while (min < max) {\n this.array[min] = callback(this.array[min], min);\n ++min;\n }\n return this;\n }\n /**\n * Receive an iterator through a section of the list.\n *\n * Negative indices can be used for min and max to indicate an offset from the\n * end of the list. For example, -2 refers to the second to last element of the list.\n *\n * **Note:** Unexpected behavior can occur if the collection is modified during iteration.\n *\n * @param min - The beginning index of the specified portion of the list, inclusive. Defaults to 0\n * @param max - The end index of the specified portion of the list, exclusive. Defaults to list.size\n *\n * @returns An iterator through the indicated section of the list\n */\n *view(min?: number, max?: number): Iterable {\n min = wrap(min ?? 0, 0, this.size);\n\n let len: () => number;\n if (max == null) {\n len = () => this.size;\n } else if (max >= 0) {\n len = () => Math.min(max, this.size);\n } else {\n len = () => this.size + max;\n }\n\n while (min < len()) {\n yield this.array[min++];\n }\n }\n}\n","import { List } from './list';\nimport { clamp, wrap } from '../utils';\n\n/**\n * A doubly-linked node version of the {@link LinkedNode} interface.\n *\n * Each node links to its neighbors on the left (prev) and right (next) of it.\n */\nexport interface DoublyLinkedNode {\n /**\n * A link to the node's next (right) neighbor\n */\n next?: DoublyLinkedNode;\n /**\n * A link to the node's previous (left) neighbor\n */\n prev?: DoublyLinkedNode;\n /**\n * The value of the node\n */\n value: T;\n}\n/**\n * A (circular) doubly-linked list implementation of the {@link List} interface.\n *\n * Operations that index into the list will traverse the list from the beginning or the end, whichever is closer to the specified index.\n */\nexport class DoublyLinkedList implements List {\n /**\n * @ignore\n * The number of elements in this list\n */\n protected length: number;\n /**\n * @ignore\n * The first node in the list\n */\n protected root: DoublyLinkedNode;\n\n constructor(elements?: Iterable) {\n this.length = 0;\n this.root = {} as DoublyLinkedNode;\n this.root.prev = this.root.next = this.root;\n this._addAll(this.root, elements ?? []);\n }\n /**\n * Add the element at the specified index.\n *\n * @param index - The index to add into (0 <= index <= size)\n * @param element - The element to add\n *\n * @returns The new size of the list\n */\n add(index: number, value: T): number {\n if (index < 0 || index > this.length) {\n return this.length;\n }\n const prev = this._get(index - 1);\n const node = { next: prev.next, prev, value };\n prev.next = node;\n node.next!.prev = node;\n return ++this.length;\n }\n /**\n * Add elements at the specified index.\n *\n * @param index - The index to add into (0 <= index <= size)\n * @param element - The elements to add\n *\n * @returns The new size of the list\n */\n addAll(index: number, elements: Iterable): number {\n if (index >= 0 && index <= this.length) {\n this._addAll(this._get(index), elements);\n }\n return this.length;\n }\n /**\n * Removes all elements\n */\n clear(): void {\n this.length = 0;\n this.root.prev = this.root.next = this.root;\n }\n /**\n * Combines the list with multiple iterables into a new list.\n * Does not modify the existing list or inputs.\n *\n * @param lists — Additional iterables to add to the end of the list.\n *\n * @returns A new list consisting of the elements in the list on which\n * it is called, followed in order by the elements of each argument. It\n * does not recurse into nested iterable arguments\n */\n concat(...lists: Iterable[]): DoublyLinkedList {\n const out = new DoublyLinkedList(this);\n for (const list of lists) {\n out.addAll(out.size, list);\n }\n return out;\n }\n /**\n * Copies a section of the list identified by min and max to the same array at position index.\n *\n * Negative indices can be used for index, min and max to indicate an offset from the\n * end of the list. For example, -2 refers to the second to last element of the list.\n *\n * Note that this method will not change the size of the list. If index is after min,\n * the copied sequence will be trimmed to fit list.size\n *\n * @param index - Where to copy the sequence to\n * @param min - Where to start copying elements from, inclusive. Defaults to 0\n * @param max - Where to end copying elements from, exclusive. Defaults to list.size\n *\n * @returns The list\n */\n copyWithin(index: number, min?: number, max?: number): this {\n // Check if copying to the same section\n index = wrap(index, 0, this.length);\n min = wrap(min ?? 0, 0, this.length);\n if (min === index) {\n return this;\n }\n\n // Check if the section to copy has no length\n max = wrap(max ?? this.length, 0, this.length);\n max = min + Math.min(max - min, this.length - index);\n if (min >= max) {\n return this;\n }\n\n // Check for overlap edge case\n if (min < index && index < max) {\n let nodeA = this._get(max);\n let nodeB = this._get(index + (max - min));\n do {\n nodeA = nodeA.prev!;\n nodeB = nodeB.prev!;\n nodeB.value = nodeA.value;\n } while (++min < max);\n return this;\n }\n\n // Copy the section to the destination\n let nodeA = this._get(min);\n let nodeB = this._get(index);\n do {\n nodeB.value = nodeA.value;\n nodeA = nodeA.next!;\n nodeB = nodeB.next!;\n } while (++min < max);\n return this;\n }\n /**\n * Returns the this object after filling the section identified by min and max with element.\n *\n * Negative indices can be used for min and max to indicate an offset from the\n * end of the list. For example, -2 refers to the second to last element of the list.\n *\n * @param element — element to fill list section with\n * @param min - Where to start filling the list, inclusive. Defaults to 0\n * @param end - Where to stop filling the list, exclusive. Defaults to list.size\n *\n * @returns The list on which this method was called\n */\n fill(element: T, min?: number, max?: number): this {\n min = wrap(min ?? 0, 0, this.length);\n max = wrap(max ?? this.length, 0, this.length);\n if (min < max) {\n let node = this._get(min);\n do {\n node.value = element;\n node = node.next!;\n } while (++min < max);\n }\n return this;\n }\n /**\n * Return the element at the specified index.\n *\n * @param index - The index to retrieve (0 <= index < size)\n *\n * @returns The element at the index, or `undefined` if index is invalid\n */\n get(index: number): T | undefined {\n return index < 0 || index >= this.length ? undefined : this._get(index).value;\n }\n /**\n * Update the element at the specified index.\n *\n * @param index - The index to retrieve (0 <= index < size)\n * @param callback - A function that receives the previous element and returns\n * the new element. The function is only called if the index is valid\n *\n * @returns The previous element at the index, or `undefined` if index is invalid\n */\n getSet(index: number, callback: (element: T) => T): T | undefined {\n if (index < 0 || index >= this.length) {\n return undefined;\n }\n const node = this._get(index);\n const value = node.value;\n node.value = callback(node.value);\n return value;\n }\n /**\n * Retrieves and removes the end of the list\n *\n * @returns The element at the end of the list, or `undefined` if empty.\n */\n pop(): T | undefined {\n if (this.length < 1) {\n return undefined;\n }\n const tail = this.root.prev!;\n tail.prev!.next = this.root;\n this.root.prev = tail.prev;\n --this.length;\n return tail.value;\n }\n /**\n * Inserts the specified element into the end of the list\n *\n * @param element - The element to be inserted\n *\n * @returns `true` upon success, otherwise `false`\n */\n push(value: T): number {\n const prev = this.root.prev!;\n const node = { next: this.root, prev, value };\n prev.next = this.root.prev = node;\n return ++this.length;\n }\n /**\n * Retrieves and removes the element at the given index.\n *\n * @param index - The index to remove (0 <= index < size)\n *\n * @returns The value at the index, or `undefined` if the index is invalid\n */\n remove(index: number): T | undefined {\n if (index < 0 || index >= this.length) {\n return undefined;\n }\n const node = this._get(index);\n node.prev!.next = node.next;\n node.next!.prev = node.prev;\n --this.length;\n return node.value;\n }\n /**\n * Reverses the elements in the list in place.\n *\n * Negative indices can be used for min and max to indicate an offset from the\n * end of the list. For example, -2 refers to the second to last element of the list.\n *\n * @param min - The beginning index of the specified portion of the list, inclusive. Defaults to 0\n * @param max - The end index of the specified portion of the list, exclusive. Defaults to list.size\n *\n * @returns a reference to the same list\n */\n reverse(min?: number, max?: number): this {\n min = wrap(min ?? 0, 0, this.length);\n max = wrap(max ?? this.length, 0, this.length);\n if (max - min < 2) {\n return this;\n }\n const root = this._get(min - 1);\n const tail = root.next!;\n let node = tail;\n do {\n const temp = node.next!;\n node.next = node.prev;\n node.prev = temp;\n root.next = node;\n node = temp;\n } while (++min < max);\n tail.next = node;\n node.prev = tail;\n root.next!.prev = root;\n return this;\n }\n /**\n * Update the element at the specified index.\n *\n * @param index - The index to retrieve (0 <= index < size)\n * @param element - The new element to insert at index\n *\n * @returns The previous element in the index, or undefined if the index is invalid\n */\n set(index: number, element: T): T | undefined {\n if (index < 0 || index >= this.length) {\n return undefined;\n }\n const node = this._get(index);\n const value = node.value;\n node.value = element;\n return value;\n }\n /**\n * Retrieves and removes the first element in the list\n *\n * @returns The element at the front of the list or `undefined` if this list is empty.\n */\n shift(): T | undefined {\n if (this.length < 1) {\n return undefined;\n }\n const head = this.root.next!;\n head.next!.prev = this.root;\n this.root.next = head.next;\n --this.length;\n return head.value;\n }\n /**\n * The number of elements in this list\n */\n get size(): number {\n return this.length;\n }\n /**\n * Returns a copy of a section of the list.\n *\n * Negative indices can be used for min and max to indicate an offset from the\n * end of the list. For example, -2 refers to the second to last element of the list.\n *\n * @param min - The beginning index of the specified portion of the list, inclusive. Defaults to 0\n * @param max - The end index of the specified portion of the list, exclusive. Defaults to list.size\n *\n * @returns A new list with a copy of the indicated section of the original list\n */\n slice(min?: number, max?: number): DoublyLinkedList {\n return new DoublyLinkedList(this.view(min, max));\n }\n /**\n * Removes elements from the list and optionally inserts new elements in their place.\n * Returns any deleted elements.\n *\n * @param start - The index from which to start removing elements. Defaults to 0\n *\n * If > size, start will be set to size. In this case, no element will be\n * deleted but the method can still add elements to the end of the list.\n *\n * If < 0, start will indicate an offset from the end of the list. For example,\n * -2 refers to the second to last element of the list.\n *\n * If < -size, start will be set to 0\n * @param count - The number of elements to remove. Defaults to size - start\n *\n * If >= size - start (that is, if it's >= than the number of elements from start\n * until the end of the list), then all the elements from start until the end of\n * the list will be removed.\n *\n * If <= 0, no elements are removed\n * @param elements - The new elements to insert at start. Defaults to none\n *\n * @returns A new list of deleted elements\n */\n splice(start?: number, count?: number, elements?: Iterable): List {\n start = wrap(start ?? 0, 0, this.size);\n count = clamp(count ?? this.size, 0, this.size - start);\n\n // If not modifying the list\n const list = new DoublyLinkedList();\n if (elements == null && count < 1) {\n return list;\n }\n\n // Delete elements\n let node = this._get(start);\n while (count-- > 0) {\n list.push(node.value);\n node.prev!.next = node.next!;\n node.next!.prev = node.prev!;\n node = node.next!;\n --this.length;\n }\n\n // Add elements\n this._addAll(node, elements ?? []);\n\n return list;\n }\n /**\n * Receive an iterator through the list.\n *\n * **Note:** Unexpected behavior can occur if the collection is modified during iteration.\n *\n * @returns An iterator through the list\n */\n *[Symbol.iterator](): Iterator {\n for (let node = this.root.next!; node !== this.root; node = node.next!) {\n yield node.value;\n }\n }\n /**\n * Inserts the specified element into the front of the list\n *\n * @param element - The element to be inserted\n *\n * @returns `true` upon success, otherwise `false`\n */\n unshift(value: T): number {\n const head = this.root.next!;\n const node = { next: head, prev: this.root, value };\n this.root.next = head.prev = node;\n return ++this.length;\n }\n /**\n * Update the elements of the list\n *\n * @param callback - A function called for each index. Returns the new element\n *\n * @returns The list on which this method was called\n */\n update(callback: (element: T, index: number) => T): this;\n /**\n * Update the elements of the list\n *\n * Negative indices can be used to indicate an offset from the\n * end of the list. For example, -2 refers to the second to last element of the list.\n *\n * @param min - Where to start filling the list, inclusive. Defaults to 0\n * @param callback - A function called for each index. Returns the new element\n *\n * @returns The list on which this method was called\n */\n update(min: number | undefined, callback: (element: T, index: number) => T): this;\n /**\n * Update the elements of the list\n *\n * Negative indices can be used for min and max to indicate an offset from the\n * end of the list. For example, -2 refers to the second to last element of the list.\n *\n * @param min - Where to start filling the list, inclusive. Defaults to 0\n * @param max - Where to stop filling the list, exclusive. Defaults to list.size\n * @param callback - A function called for each index. Returns the new element\n *\n * @returns The list on which this method was called\n */\n update(\n min: number | undefined,\n max: number | undefined,\n callback: (element: T, index: number) => T,\n ): this;\n update(\n min: number | undefined | ((element: T, index: number) => T),\n max?: number | ((element: T, index: number) => T),\n callback?: (element: T, index: number) => T,\n ): this {\n if (callback == null) {\n if (arguments.length < 2) {\n callback = min as (element: T, index: number) => T;\n min = undefined;\n } else {\n callback = max as (element: T, index: number) => T;\n max = undefined;\n }\n }\n min = wrap((min as number) ?? 0, 0, this.length);\n max = wrap((max as number) ?? this.length, 0, this.length);\n if (min < max) {\n let node = this._get(min);\n do {\n node.value = callback(node.value, min);\n node = node.next!;\n } while (++min < max);\n }\n return this;\n }\n /**\n * Receive an iterator through a section of the list.\n *\n * Negative indices can be used for min and max to indicate an offset from the\n * end of the list. For example, -2 refers to the second to last element of the list.\n *\n * **Note:** Unexpected behavior can occur if the collection is modified during iteration.\n *\n * @param min - The beginning index of the specified portion of the list, inclusive. Defaults to 0\n * @param max - The end index of the specified portion of the list, exclusive. Defaults to list.size\n *\n * @returns An iterator through the indicated section of the list\n */\n *view(min?: number, max?: number): Iterable {\n min = wrap(min ?? 0, 0, this.length);\n\n let len: () => number;\n if (max == null) {\n len = () => this.length;\n } else if (max >= 0) {\n len = () => max;\n } else {\n len = () => this.length + max;\n }\n\n if (min < len()) {\n let node = this._get(min);\n do {\n yield node.value;\n node = node.next!;\n } while (++min < len() && node !== this.root);\n }\n }\n /**\n * @ignore\n *\n */\n protected _addAll(next: DoublyLinkedNode, elements: Iterable): void {\n let prev = next.prev!;\n for (const value of elements) {\n const node = { prev, value };\n prev.next = node;\n prev = node;\n ++this.length;\n }\n prev.next = next;\n next.prev = prev;\n }\n /**\n * @ignore\n * A helper method to iterate and return the node at the given index.\n *\n * Depending on the index, the list will be traversed from beginning or end; whichever is closest to the specified index.\n *\n * @param index - The index to retrieve\n *\n * @returns The node at the given index\n */\n protected _get(index: number): DoublyLinkedNode {\n let node = this.root;\n if (index < this.length / 2) {\n while (index-- >= 0) {\n node = node.next!;\n }\n } else {\n for (index = this.length - index; index > 0; --index) {\n node = node.prev!;\n }\n }\n return node;\n }\n}\n","import { List } from './list';\nimport { clamp, wrap } from '../utils';\n\n/**\n * A linked node interface.\n *\n * Each node links to its next neighbor.\n */\nexport interface LinkedNode {\n /**\n * A link to the node's neighbor\n */\n next?: LinkedNode;\n /**\n * The value of the node\n */\n value: T;\n}\n/**\n * A (circular) linked list implementation of the {@link List} interface.\n */\nexport class LinkedList implements List {\n /**\n * @ignore\n */\n protected length: number;\n /**\n * @ignore\n */\n protected root: LinkedNode;\n /**\n * @ignore\n */\n protected tail: LinkedNode;\n\n constructor(elements?: Iterable) {\n this.length = 0;\n this.root = {} as LinkedNode;\n this.root.next = this.root;\n this.tail = this._addAll(this.root, elements ?? []);\n }\n /**\n * Add the element at the specified index.\n *\n * @param index - The index to add into (0 <= index <= size)\n * @param element - The element to add\n *\n * @returns The new size of the list\n */\n add(index: number, value: T): number {\n if (index >= 0 && index < this.length) {\n const prev = this._get(index - 1);\n prev.next = { value, next: prev.next };\n ++this.length;\n } else if (index === this.length) {\n this.push(value);\n }\n return this.length;\n }\n /**\n * Add elements at the specified index.\n *\n * @param index - The index to add into (0 <= index <= size)\n * @param element - The elements to add\n *\n * @returns The new size of the list\n */\n addAll(index: number, elements: Iterable): number {\n if (index >= 0 && index < this.length) {\n this._addAll(this._get(index - 1), elements);\n } else if (index === this.length) {\n this.tail = this._addAll(this.tail, elements);\n }\n return this.length;\n }\n /**\n * Removes all elements\n */\n clear(): void {\n this.length = 0;\n this.tail = this.root.next = this.root;\n }\n /**\n * Combines the list with multiple iterables into a new list.\n * Does not modify the existing list or inputs.\n *\n * @param lists — Additional iterables to add to the end of the list.\n *\n * @returns A new list consisting of the elements in the list on which\n * it is called, followed in order by the elements of each argument. It\n * does not recurse into nested iterable arguments\n */\n concat(...lists: Iterable[]): LinkedList {\n const out = new LinkedList(this);\n for (const list of lists) {\n out.addAll(out.size, list);\n }\n return out;\n }\n /**\n * Copies a section of the list identified by min and max to the same array at position index.\n *\n * Negative indices can be used for index, min and max to indicate an offset from the\n * end of the list. For example, -2 refers to the second to last element of the list.\n *\n * Note that this method will not change the size of the list. If index is after min,\n * the copied sequence will be trimmed to fit list.size\n *\n * @param index - Where to copy the sequence to\n * @param min - Where to start copying elements from, inclusive. Defaults to 0\n * @param max - Where to end copying elements from, exclusive. Defaults to list.size\n *\n * @returns The list\n */\n copyWithin(index: number, min?: number, max?: number): this {\n // Check if copying to itself\n index = wrap(index, 0, this.length);\n min = wrap(min ?? 0, 0, this.length);\n if (min === index) {\n return this;\n }\n\n // Check if the section to copy has no length\n max = wrap(max ?? this.length, 0, this.length);\n max = min + Math.min(max - min, this.length - index);\n if (min >= max) {\n return this;\n }\n\n // Copy to earlier in the list\n if (index < min) {\n const node = this._get(index - 1);\n this._copyWithin(this._get(min - index - 1, node), node, max - min);\n return this;\n }\n\n // Copy to later in the list\n if (index > max) {\n const node = this._get(min - 1);\n this._copyWithin(node, this._get(index - min - 1, node), max - min);\n return this;\n }\n\n // Copy to overlapping destination\n const nodeA = this._get(min - 1);\n const nodeC = this._get(max - min - 1, nodeA);\n const nodeD = this._copyWithin(nodeA, nodeC, index - min);\n if (index + (max - min) >= this.length) {\n this.tail = nodeC;\n }\n const temp = nodeA.next;\n nodeA.next = nodeC.next;\n nodeC.next = nodeD.next;\n nodeD.next = temp;\n return this;\n }\n /**\n * Returns the this object after filling the section identified by min and max with element.\n *\n * Negative indices can be used for min and max to indicate an offset from the\n * end of the list. For example, -2 refers to the second to last element of the list.\n *\n * @param element — element to fill list section with\n * @param min - Where to start filling the list, inclusive. Defaults to 0\n * @param end - Where to stop filling the list, exclusive. Defaults to list.size\n *\n * @returns The list on which this method was called\n */\n fill(element: T, min?: number, max?: number): this {\n min = wrap(min ?? 0, 0, this.length);\n max = wrap(max ?? this.length, 0, this.length);\n if (min < max) {\n let node = this._get(min);\n do {\n node.value = element;\n node = node.next!;\n } while (++min < max);\n }\n return this;\n }\n /**\n * Return the element at the specified index.\n *\n * @param index - The index to retrieve (0 <= index < size)\n *\n * @returns The element at the index, or `undefined` if index is invalid\n */\n get(index: number): T | undefined {\n if (index < 0 || index >= this.length) {\n return undefined;\n }\n return index < this.length - 1 ? this._get(index).value : this.tail.value;\n }\n /**\n * Update the element at the specified index.\n *\n * @param index - The index to retrieve (0 <= index < size)\n * @param callback - A function that receives the previous element and returns\n * the new element. The function is only called if the index is valid\n *\n * @returns The previous element at the index, or `undefined` if index is invalid\n */\n getSet(index: number, callback: (element: T) => T): T | undefined {\n if (index < 0 || index >= this.length) {\n return undefined;\n }\n const node = index < this.length - 1 ? this._get(index) : this.tail;\n const value = node.value;\n node.value = callback(node.value);\n return value;\n }\n /**\n * Retrieves and removes the end of the list\n *\n * @returns The value at the end of the list, or `undefined` if empty.\n */\n pop(): T | undefined {\n if (this.length < 1) {\n return undefined;\n }\n const value = this.tail.value;\n this.tail = this._get(this.length - 2);\n this.tail.next = this.root;\n --this.length;\n return value;\n }\n /**\n * Inserts the specified value into the end of the list\n *\n * @param element - The element to be inserted\n *\n * @returns `true` upon success, otherwise `false`\n */\n push(value: T): number {\n const tail: LinkedNode = { next: this.root, value };\n this.tail.next = tail;\n this.tail = tail;\n return ++this.length;\n }\n /**\n * Retrieves and removes the element at the given index.\n *\n * @param index - The index to remove (0 <= index < size)\n *\n * @returns The value at the index, or `undefined` if the index is invalid\n */\n remove(index: number): T | undefined {\n if (index < 0 || index >= this.length) {\n return undefined;\n }\n const prev = this._get(index - 1);\n const node = prev.next!;\n prev.next = node.next;\n if (index === --this.length) {\n this.tail = prev;\n }\n return node.value;\n }\n /**\n * Reverses the elements in the list in place.\n *\n * Negative indices can be used for min and max to indicate an offset from the\n * end of the list. For example, -2 refers to the second to last element of the list.\n *\n * @param min - The beginning index of the specified portion of the list, inclusive. Defaults to 0\n * @param max - The end index of the specified portion of the list, exclusive. Defaults to list.size\n *\n * @returns a reference to the same list\n */\n reverse(min?: number, max?: number): this {\n min = wrap(min ?? 0, 0, this.length);\n max = wrap(max ?? this.length, 0, this.length);\n if (max - min < 2) {\n return this;\n }\n const root = this._get(min - 1);\n this.tail = max >= this.length ? root.next! : this.tail;\n const tail = root.next!;\n let prev = tail;\n let node = tail.next!;\n while (++min < max) {\n const next = node.next!;\n node.next = prev;\n prev = node;\n node = next;\n }\n root.next = prev;\n tail.next = node;\n return this;\n }\n /**\n * Update the element at the specified index.\n *\n * @param index - The index to retrieve (0 <= index < size)\n * @param element - The new element to insert at index\n *\n * @returns The previous element in the index, or undefined if the index is invalid\n */\n set(index: number, element: T): T | undefined {\n if (index < 0 || index >= this.length) {\n return undefined;\n }\n const node = this._get(index);\n const value = node.value;\n node.value = element;\n return value;\n }\n /**\n * Retrieves and removes the first element in the list\n *\n * @returns The value at the front of the list or `undefined` if this list is empty.\n */\n shift(): T | undefined {\n return this.remove(0);\n }\n /**\n * The number of elements in this list\n */\n get size(): number {\n return this.length;\n }\n /**\n * Returns a copy of a section of the list.\n *\n * Negative indices can be used for min and max to indicate an offset from the\n * end of the list. For example, -2 refers to the second to last element of the list.\n *\n * @param min - The beginning index of the specified portion of the list, inclusive. Defaults to 0\n * @param max - The end index of the specified portion of the list, exclusive. Defaults to list.size\n *\n * @returns A new list with a copy of the indicated section of the original list\n */\n slice(min?: number, max?: number): LinkedList {\n return new LinkedList(this.view(min, max));\n }\n /**\n * Removes elements from the list and optionally inserts new elements in their place.\n * Returns any deleted elements.\n *\n * @param start - The index from which to start removing elements. Defaults to 0\n *\n * If > size, start will be set to size. In this case, no element will be\n * deleted but the method can still add elements to the end of the list.\n *\n * If < 0, start will indicate an offset from the end of the list. For example,\n * -2 refers to the second to last element of the list.\n *\n * If < -size, start will be set to 0\n * @param count - The number of elements to remove. Defaults to size - start\n *\n * If >= size - start (that is, if it's >= than the number of elements from start\n * until the end of the list), then all the elements from start until the end of\n * the list will be removed.\n *\n * If <= 0, no elements are removed\n * @param elements - The new elements to insert at start. Defaults to none\n *\n * @returns A new list of deleted elements\n */\n splice(start?: number, count?: number, elements?: Iterable): List {\n start = wrap(start ?? 0, 0, this.size);\n count = clamp(count ?? this.size, 0, this.size - start);\n\n // If not modifying the list\n const deleted = new LinkedList();\n if (elements == null && count < 1) {\n return deleted;\n }\n\n // Delete elements\n let prev = this._get(start - 1);\n const newTail = start + count >= this.size;\n while (count-- > 0) {\n const node = prev.next!;\n deleted.push(node.value);\n prev.next = node.next;\n --this.length;\n }\n\n // Add elements\n prev = this._addAll(prev, elements ?? []);\n this.tail = newTail ? prev : this.tail;\n\n return deleted;\n }\n /**\n * Receive an iterator through the list.\n *\n * **Note:** Unexpected behavior can occur if the collection is modified during iteration.\n *\n * @returns An iterator through the list\n */\n *[Symbol.iterator](): Iterator {\n for (let node = this.root.next!; node !== this.root; node = node.next!) {\n yield node.value;\n }\n }\n /**\n * Inserts the specified value into the front of the list\n *\n * @param element - The element to be inserted\n *\n * @returns `true` upon success, otherwise `false`\n */\n unshift(value: T): number {\n return this.add(0, value);\n }\n /**\n * Update the elements of the list\n *\n * @param callback - A function called for each index. Returns the new element\n *\n * @returns The list on which this method was called\n */\n update(callback: (element: T, index: number) => T): this;\n /**\n * Update the elements of the list\n *\n * Negative indices can be used to indicate an offset from the\n * end of the list. For example, -2 refers to the second to last element of the list.\n *\n * @param min - Where to start filling the list, inclusive. Defaults to 0\n * @param callback - A function called for each index. Returns the new element\n *\n * @returns The list on which this method was called\n */\n update(min: number | undefined, callback: (element: T, index: number) => T): this;\n /**\n * Update the elements of the list\n *\n * Negative indices can be used for min and max to indicate an offset from the\n * end of the list. For example, -2 refers to the second to last element of the list.\n *\n * @param min - Where to start filling the list, inclusive. Defaults to 0\n * @param max - Where to stop filling the list, exclusive. Defaults to list.size\n * @param callback - A function called for each index. Returns the new element\n *\n * @returns The list on which this method was called\n */\n update(\n min: number | undefined,\n max: number | undefined,\n callback: (element: T, index: number) => T,\n ): this;\n update(\n min: number | undefined | ((element: T, index: number) => T),\n max?: number | ((element: T, index: number) => T),\n callback?: (element: T, index: number) => T,\n ): this {\n if (callback == null) {\n if (arguments.length < 2) {\n callback = min as (element: T, index: number) => T;\n min = undefined;\n } else {\n callback = max as (element: T, index: number) => T;\n max = undefined;\n }\n }\n min = wrap((min as number) ?? 0, 0, this.length);\n max = wrap((max as number) ?? this.length, 0, this.length);\n if (min < max) {\n let node = this._get(min);\n do {\n node.value = callback(node.value, min);\n node = node.next!;\n } while (++min < max);\n }\n return this;\n }\n /**\n * Receive an iterator through a section of the list.\n *\n * Negative indices can be used for min and max to indicate an offset from the\n * end of the list. For example, -2 refers to the second to last element of the list.\n *\n * **Note:** Unexpected behavior can occur if the collection is modified during iteration.\n *\n * @param min - The beginning index of the specified portion of the list, inclusive. Defaults to 0\n * @param max - The end index of the specified portion of the list, exclusive. Defaults to list.size\n *\n * @returns An iterator through the indicated section of the list\n */\n *view(min?: number, max?: number): Iterable {\n min = wrap(min ?? 0, 0, this.length);\n\n let len: () => number;\n if (max == null) {\n len = () => this.length;\n } else if (max >= 0) {\n len = () => max;\n } else {\n len = () => this.length + max;\n }\n\n if (min < len()) {\n let node = this._get(min);\n do {\n yield node.value;\n node = node.next!;\n } while (++min < len() && node !== this.root);\n }\n }\n protected _addAll(prev: LinkedNode, elements: Iterable): LinkedNode {\n const next = prev.next!;\n for (const value of elements) {\n const node = { value };\n prev.next = node;\n prev = node;\n ++this.length;\n }\n prev.next = next;\n return prev;\n }\n /**\n * @ignore\n * Copy values from 'from' to 'to'.\n *\n * @param from - The initial node to copy from\n * @param prev - The root of the initial node to copy to\n * @param count - The number of values to copy\n */\n protected _copyWithin(from: LinkedNode, to: LinkedNode, count: number): LinkedNode {\n while (count-- > 0) {\n from = from.next!;\n to = to.next!;\n to.value = from.value;\n }\n return to;\n }\n /**\n * @ignore\n * Get the node at the given index.\n *\n * @param index - The index to retrieve\n *\n * @returns The node at the given index\n */\n protected _get(index: number, root: LinkedNode = this.root): LinkedNode {\n let node = root!;\n while (index-- >= 0) {\n node = node.next!;\n }\n return node;\n }\n}\n","import { Queue } from './queue';\n\n/**\n * An implementation of the {@link Queue} interface using an array\n */\nexport class ArrayQueue implements Queue {\n /**\n * @ignore\n */\n protected array: T[];\n\n constructor(elements?: Iterable) {\n this.array = elements ? Array.from(elements) : [];\n }\n /**\n * Removes all elements from this queue\n */\n clear(): void {\n this.array.length = 0;\n }\n /**\n * Retrieves and removes the head of this queue\n *\n * @returns The element at the head of the queue or `undefined` if this queue is empty.\n */\n dequeue(): T | undefined {\n return this.size < 1 ? undefined : this.array.shift();\n }\n /**\n * Inserts the specified element into this queue\n *\n * @param element - The element to be inserted\n */\n enqueue(element: T): number {\n return this.array.push(element);\n }\n /**\n * Retrieves, but does not remove, the head of this queue\n *\n * @returns The value at the head of the queue or `undefined` if this queue is empty.\n */\n peek(): T | undefined {\n return this.size < 1 ? undefined : this.array[0];\n }\n /**\n * The number of elements in this queue\n */\n get size(): number {\n return this.array.length;\n }\n /**\n * Receive an iterator through the queue.\n *\n * **Note:** Unexpected behavior can occur if the collection is modified during iteration.\n *\n * @returns An iterator through the queue\n */\n [Symbol.iterator](): Iterator {\n return this.array[Symbol.iterator]();\n }\n}\n","import { LinkedList, List } from '../list';\nimport { Queue } from './queue';\n\n/**\n * A linked list implementation of the {@link Queue} interface\n */\nexport class LinkedQueue implements Queue {\n /**\n * @ignore\n */\n protected list: List;\n\n constructor(elements?: Iterable) {\n this.list = new LinkedList(elements);\n }\n /**\n * Removes all elements from this queue\n */\n clear(): void {\n this.list.clear();\n }\n /**\n * Retrieves and removes the head of this queue\n *\n * @returns The element at the head of the queue or `undefined` if this queue is empty.\n */\n dequeue(): T | undefined {\n return this.list.shift();\n }\n /**\n * Inserts the specified element into this queue\n *\n * @param element - The element to be inserted\n */\n enqueue(element: T): number {\n return this.list.push(element);\n }\n /**\n * Retrieves, but does not remove, the head of this queue\n *\n * @returns The element at the head of the queue or `undefined` if this queue is empty.\n */\n peek(): T | undefined {\n return this.list.get(0);\n }\n /**\n * The number of elements in this queue\n */\n get size(): number {\n return this.list.size;\n }\n /**\n * Receive an iterator through the queue.\n *\n * **Note:** Unexpected behavior can occur if the collection is modified during iteration.\n *\n * @returns An iterator through the queue\n */\n [Symbol.iterator](): Iterator {\n return this.list[Symbol.iterator]();\n }\n}\n","import { Stack } from './stack';\n\n/**\n * An implementation of the {@link Stack} interface using an array\n */\nexport class ArrayStack implements Stack {\n /**\n * @ignore\n */\n protected array: T[];\n\n constructor(elements?: Iterable) {\n this.array = elements ? Array.from(elements) : [];\n }\n /**\n * Removes all elements from the stack\n */\n clear(): void {\n this.array.length = 0;\n }\n /**\n * Retrieves, but does not remove, the top of the stack\n *\n * @returns The element at the top of the stack or `undefined` if empty.\n */\n peek(): T | undefined {\n return this.array[this.array.length - 1];\n }\n /**\n * Retrieves and removes the top of the stack\n *\n * @returns The element at the top of the stack or `undefined` if empty.\n */\n pop(): T | undefined {\n return this.array.pop();\n }\n /**\n * Inserts a element into the stack\n *\n * @param element - The element to be inserted\n *\n * @returns The new size of the stack\n */\n push(element: T): number {\n return this.array.push(element);\n }\n /**\n * The number of elements in the stack\n */\n get size(): number {\n return this.array.length;\n }\n /**\n * Receive an iterator through the stack.\n *\n * **Note:** Unexpected behavior can occur if the collection is modified during iteration.\n *\n * @returns An iterator through the stack\n */\n *[Symbol.iterator](): Iterator {\n const array = this.array;\n for (let i = array.length; i > 0; yield array[--i]) {}\n }\n}\n","import { LinkedList, List } from '../list';\nimport { Stack } from './stack';\n\n/**\n * A linked list implementation of the {@link Stack} interface\n */\nexport class LinkedStack implements Stack {\n /**\n * @ignore\n */\n protected list: List;\n\n constructor(elements?: Iterable) {\n this.list = new LinkedList();\n for (const element of elements || []) {\n this.push(element);\n }\n }\n /**\n * Removes all elements from the stack\n */\n clear(): void {\n this.list.clear();\n }\n /**\n * Retrieves, but does not remove, the top of the stack\n *\n * @returns The element at the top of the stack or `undefined` if empty.\n */\n peek(): T | undefined {\n return this.list.get(0);\n }\n /**\n * Retrieves and removes the top of the stack\n *\n * @returns The element at the top of the stack or `undefined` if empty.\n */\n pop(): T | undefined {\n return this.list.shift();\n }\n /**\n * Inserts a element into the stack\n *\n * @param element - The element to be inserted\n *\n * @returns The new size of the stack\n */\n push(element: T): number {\n return this.list.unshift(element);\n }\n /**\n * The number of elements in the stack\n */\n get size(): number {\n return this.list.size;\n }\n /**\n * Receive an iterator through the stack.\n *\n * **Note:** Unexpected behavior can occur if the collection is modified during iteration.\n *\n * @returns An iterator through the stack\n */\n [Symbol.iterator](): Iterator {\n return this.list[Symbol.iterator]();\n }\n}\n","/**\n * @ignore\n */\nexport function* batch(size: number, elements: Iterable): Generator {\n let array: T[] = [];\n for (const element of elements) {\n if (array.push(element) >= size) {\n yield array;\n array = [];\n }\n }\n if (array.length > 0) {\n yield array;\n }\n}\n/**\n * @ignore\n */\nexport function clamp(num: number, min: number, max: number): number {\n return Math.min(max, Math.max(min, num));\n} /*\nexport function* first(num: number, iterator: Iterator): Generator {\n while (num-- > 0) {\n const res = iterator.next();\n if (res.done) {\n break;\n }\n yield res.value;\n }\n}\n*/ /*\nexport function* iterate(iterator: Iterator): Generator {\n let res = iterator.next();\n while (!res.done) {\n yield res.value;\n res = iterator.next();\n }\n}\n*/\n/**\n * @ignore\n */\n/**\n * @ignore\n */\n/**\n * @ignore\n */ export function wrap(num: number, min: number, max: number): number {\n return clamp(num < 0 ? max + num : num, min, max);\n}\n","// The module cache\nvar __webpack_module_cache__ = {};\n\n// The require function\nfunction __webpack_require__(moduleId) {\n\t// Check if module is in cache\n\tvar cachedModule = __webpack_module_cache__[moduleId];\n\tif (cachedModule !== undefined) {\n\t\treturn cachedModule.exports;\n\t}\n\t// Create a new module (and put it into the cache)\n\tvar module = __webpack_module_cache__[moduleId] = {\n\t\t// no module.id needed\n\t\t// no module.loaded needed\n\t\texports: {}\n\t};\n\n\t// Execute the module function\n\t__webpack_modules__[moduleId](module, module.exports, __webpack_require__);\n\n\t// Return the exports of the module\n\treturn module.exports;\n}\n\n","// getDefaultExport function for compatibility with non-harmony modules\n__webpack_require__.n = (module) => {\n\tvar getter = module && module.__esModule ?\n\t\t() => (module['default']) :\n\t\t() => (module);\n\t__webpack_require__.d(getter, { a: getter });\n\treturn getter;\n};","// define getter functions for harmony exports\n__webpack_require__.d = (exports, definition) => {\n\tfor(var key in definition) {\n\t\tif(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {\n\t\t\tObject.defineProperty(exports, key, { enumerable: true, get: definition[key] });\n\t\t}\n\t}\n};","__webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))","// define __esModule on exports\n__webpack_require__.r = (exports) => {\n\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n\t}\n\tObject.defineProperty(exports, '__esModule', { value: true });\n};"],"sourceRoot":""} \ No newline at end of file +{"version":3,"sources":["webpack://Dastal/webpack/universalModuleDefinition","webpack://Dastal/./src/array/utils.ts","webpack://Dastal/./src/heap/binaryHeap.ts","webpack://Dastal/./src/tree/utils.ts","webpack://Dastal/./src/heap/skewHeap.ts","webpack://Dastal/./src/heap/utils.ts","webpack://Dastal/./src/list/arrayList.ts","webpack://Dastal/./src/list/doublyLinkedList.ts","webpack://Dastal/./src/list/linkedList.ts","webpack://Dastal/./src/list/utils.ts","webpack://Dastal/./src/queue/arrayQueue.ts","webpack://Dastal/./src/queue/linkedQueue.ts","webpack://Dastal/./src/stack/arrayStack.ts","webpack://Dastal/./src/stack/linkedStack.ts","webpack://Dastal/webpack/bootstrap","webpack://Dastal/webpack/runtime/compat get default export","webpack://Dastal/webpack/runtime/define property getters","webpack://Dastal/webpack/runtime/hasOwnProperty shorthand","webpack://Dastal/webpack/runtime/make namespace object"],"names":["root","factory","exports","module","define","amd","self","MAX_ARRAY_LENGTH","Symbol","iterator","BinaryHeap","compareFn","elements","this","compare","array","addAll","length","element","RangeError","push","heapify","indexOf","index","last","pop","sinkDown","bubbleUp","value","heap","size","dump","undefined","a","b","curElement","newElement","preOrderTraverse","clone","node","out","Object","assign","stack","LinkedStack","left","right","toBinaryTree","n","nodes","Array","i","par","SkewHeap","key","skewMerge","parentIndex","Math","floor","parent","childIndex","child","heaps","list","LinkedList","sort","shift","next","ArrayList","from","splice","batch","items","lists","min","max","cwrap","copyWithin","fill","callback","temp","prev","slice","start","count","clamp","unshift","arguments","len","DoublyLinkedList","_addAll","_get","nodeA","nodeB","tail","head","view","mergeSort","_copyWithin","nodeC","nodeD","remove","deleted","newTail","add","to","iterable","f","num","pivot","wrap","isDoubly","lens","ceil","heads","tails","mergeSorted","ArrayQueue","LinkedQueue","clear","get","ArrayStack","__webpack_module_cache__","__webpack_require__","moduleId","cachedModule","__webpack_modules__","getter","__esModule","d","definition","o","defineProperty","enumerable","obj","prop","prototype","hasOwnProperty","call","r","toStringTag"],"mappings":"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","file":"dastal.min.js","sourcesContent":["(function webpackUniversalModuleDefinition(root, factory) {\n\tif(typeof exports === 'object' && typeof module === 'object')\n\t\tmodule.exports = factory();\n\telse if(typeof define === 'function' && define.amd)\n\t\tdefine(\"Dastal\", [], factory);\n\telse if(typeof exports === 'object')\n\t\texports[\"Dastal\"] = factory();\n\telse\n\t\troot[\"Dastal\"] = factory();\n})(self, function() {\nreturn ","/**\n * The maximum length of an array.\n *\n * According to [ECMA-262](https://tc39.es/ecma262/#array-index):\n * 0 <= array.length <= 2^32 - 1\n */\nexport const MAX_ARRAY_LENGTH = 4294967295;\n","import { MAX_ARRAY_LENGTH } from 'src/array/utils';\nimport { CompareFn } from '..';\nimport { Heap } from './heap';\nimport { SkewHeap } from './skewHeap';\nimport { bubbleUp, heapify, sinkDown } from './utils';\n\n/**\n *\n */\nexport class BinaryHeap implements Heap {\n /**\n * The array containing every element.\n */\n protected array: T[];\n /**\n * The function to determine the order of elements.\n */\n protected compare: CompareFn;\n /**\n * Instantiate a heap.\n *\n * @param compareFn - The function to determine the order of elements.\n * @param elements - A set of elements to initialize the list with.\n */\n constructor(compareFn: CompareFn, elements?: Iterable) {\n this.compare = compareFn;\n this.array = [];\n this.addAll(elements ?? []);\n }\n\n addAll(elements: Iterable): number {\n const array = this.array;\n\n // Add new elements\n const length = array.length;\n for (const element of elements) {\n if (array.length >= MAX_ARRAY_LENGTH) {\n throw new RangeError('Invalid heap length');\n }\n array.push(element);\n }\n\n // Update the heap\n if (length < array.length) {\n heapify(this.compare, array);\n }\n\n return array.length;\n }\n\n clear(): void {\n this.array.length = 0;\n }\n\n comparator(): CompareFn {\n return this.compare;\n }\n\n contains(element: T): boolean {\n return this.array.indexOf(element) >= 0;\n }\n\n delete(element: T): boolean {\n const index = this.array.indexOf(element);\n if (index < 0) {\n return false;\n }\n\n // If deleting the last value\n const last = this.array.pop()!;\n if (index >= this.array.length) {\n return true;\n }\n\n // Add the last value to the\n // deleted index and update the heap\n this.array[index] = last;\n sinkDown(index, this.compare, this.array);\n bubbleUp(index, this.compare, this.array);\n return true;\n }\n\n *dump(): Iterable {\n for (const value of this.array) {\n yield value;\n }\n }\n\n merge(heap: Heap): this {\n const array = this.array;\n\n if (heap.size < 1) {\n return this;\n }\n if (array.length + heap.size > MAX_ARRAY_LENGTH) {\n throw new RangeError('Invalid heap length');\n }\n\n const elements = heap instanceof BinaryHeap ? heap.array : heap.dump();\n for (const element of elements) {\n array.push(element);\n }\n\n heapify(this.compare, array);\n return this;\n }\n\n peek(): T | undefined {\n return this.array.length > 0 ? this.array[0] : undefined;\n }\n\n pop(): T | undefined {\n if (this.array.length < 1) {\n return undefined;\n }\n\n // Get the root and the last value\n const value = this.array[0];\n const last = this.array.pop();\n\n // If value != last\n if (this.array.length > 0) {\n // Move the last value to the root and update the heap\n this.array[0] = last!;\n sinkDown(0, this.compare, this.array);\n }\n\n return value;\n }\n\n push(value: T): number {\n // Add new value to the end of the heap\n this.array.push(value);\n\n // Update the heap\n bubbleUp(this.array.length - 1, this.compare, this.array);\n return this.size;\n }\n\n pushPop(value: T): T {\n // If empty or value is <= to root\n if (this.array.length < 1 || this.compare(value, this.array[0]) <= 0) {\n return value;\n }\n\n // Swap the root and value\n const root = this.array[0];\n this.array[0] = value;\n sinkDown(0, this.compare, this.array);\n return root;\n }\n\n replace(value: T): T | undefined {\n // If empty\n if (this.array.length < 1) {\n this.array.push(value);\n return undefined;\n }\n\n // Swap the root with value\n const root = this.array[0];\n this.array[0] = value;\n value = root;\n\n // Update the heap\n sinkDown(0, this.compare, this.array);\n return value;\n }\n\n get size(): number {\n return this.array.length;\n }\n /**\n * Iterate through the heap in sorted order.\n *\n * **Note:** Unexpected behavior can occur if the collection is modified during iteration.\n *\n * @returns An iterator through the heap.\n */\n *[Symbol.iterator](): Iterator {\n if (this.array.length < 1) {\n return;\n }\n const array = this.array;\n const heap = new BinaryHeap((a, b) => this.compare(array[a], array[b]), [0]);\n do {\n let index = heap.pop()!;\n if (index < array.length) {\n yield array[index];\n index = 2 * index + 1;\n index < array.length && heap.push(index);\n ++index < array.length && heap.push(index);\n }\n } while (heap.size > 0);\n }\n\n update(curElement: T, newElement: T): boolean {\n const index = this.array.indexOf(curElement);\n if (index < 0) {\n return false;\n }\n this.array[index] = newElement;\n sinkDown(index, this.compare, this.array);\n bubbleUp(index, this.compare, this.array);\n return true;\n }\n}\n","import { LinkedStack } from 'src/stack';\nimport { BinaryTreeNode } from '.';\n\n/**\n *\n * @param node\n *\n * @returns\n *\n * @internal\n */\nexport function clone(node: BinaryTreeNode | undefined): BinaryTreeNode | undefined {\n if (node == null) {\n return undefined;\n }\n const out: BinaryTreeNode = Object.assign({}, node);\n const stack = new LinkedStack>([out]);\n do {\n node = stack.pop()!;\n if (node.left) {\n stack.push((node.left = Object.assign({}, node.left)));\n } else if (node.right) {\n stack.push((node.right = Object.assign({}, node.right)));\n }\n } while (stack.size > 0);\n return out;\n}\n/**\n *\n * @param elements\n *\n * @returns\n *\n * @internal\n */\nexport function toBinaryTree(elements: T[] | undefined): BinaryTreeNode | undefined {\n if (elements == null || elements.length < 1) {\n return undefined;\n }\n const n = elements.length;\n const nodes = new Array(n);\n nodes[0] = { value: elements[0] };\n for (let i = 1; i < n; ++i) {\n const par = nodes[(i - 1) >>> 1];\n const node = { value: elements[i] };\n nodes[i] = node;\n if (i & 1) {\n par.left = node;\n } else {\n par.right = node;\n }\n }\n return nodes[0];\n}\n/**\n *\n * @param node\n *\n * @returns\n *\n * @internal\n */\nexport function* inOrderTraverse(\n node: BinaryTreeNode | undefined,\n): Iterable> {\n const stack = new LinkedStack>();\n\n while (node != null) {\n stack.push(node);\n node = node.left;\n }\n\n while (stack.size > 0) {\n node = stack.pop()!;\n yield node;\n node = node.right;\n while (node != null) {\n stack.push(node);\n node = node.left;\n }\n }\n}\n/**\n *\n * @param node\n *\n * @returns\n *\n * @internal\n */\nexport function* postOrderTraverse(\n node: BinaryTreeNode | undefined,\n): Iterable> {\n interface Meta {\n seen: boolean;\n node?: BinaryTreeNode;\n }\n const stack = new LinkedStack([{ seen: false, node }]);\n do {\n const meta = stack.pop()!;\n if (meta.node != null) {\n if (meta.seen) {\n yield meta.node;\n } else {\n meta.seen = true;\n stack.push(meta);\n stack.push({ seen: false, node: meta.node.right });\n stack.push({ seen: false, node: meta.node.left });\n }\n }\n } while (stack.size > 0);\n}\n/**\n *\n * @param node\n *\n * @returns\n *\n * @internal\n */\nexport function* preOrderTraverse(\n node: BinaryTreeNode | undefined,\n): Iterable> {\n const stack = new LinkedStack | undefined>([node]);\n do {\n node = stack.pop()!;\n if (node != null) {\n yield node;\n stack.push(node.right);\n stack.push(node.left);\n }\n } while (stack.size > 0);\n}\n","import { BinaryTreeNode } from 'src/tree';\nimport { clone, preOrderTraverse, toBinaryTree } from 'src/tree/utils';\nimport { CompareFn } from '..';\nimport { BinaryHeap } from './binaryHeap';\nimport { Heap } from './heap';\nimport { skewMerge } from './utils';\n\n/**\n *\n */\nexport class SkewHeap implements Heap {\n /**\n * The function to determine the order of elements.\n */\n protected compare: CompareFn;\n /**\n * The number of elements in the list.\n */\n protected length: number;\n /**\n * The node at the \"top\" of the heap.\n */\n protected root: BinaryTreeNode | undefined;\n /**\n * Instantiate a heap.\n *\n * @param compareFn - The function to determine the order of elements.\n * @param elements - A set of elements to initialize the list with.\n */\n constructor(compareFn: CompareFn, elements?: Iterable) {\n this.compare = compareFn;\n this.length = 0;\n this.addAll(elements ?? []);\n }\n\n addAll(elements: Iterable): number {\n for (const element of elements) {\n this.push(element);\n }\n return this.length;\n }\n\n clear(): void {\n this.length = 0;\n this.root = undefined;\n }\n\n comparator(): CompareFn {\n return this.compare;\n }\n\n contains(element: T): boolean {\n for (const node of preOrderTraverse(this.root)) {\n if (element === node.value) {\n return true;\n }\n }\n return false;\n }\n\n delete(element: T): boolean {\n if (this.root == null) {\n return false;\n }\n if (this.root.value === element) {\n this.pop()!;\n return true;\n }\n for (const par of preOrderTraverse(this.root)) {\n const key: keyof BinaryTreeNode | undefined =\n par.left && par.left.value === element\n ? 'left'\n : par.right && par.right.value === element\n ? 'right'\n : undefined;\n if (key != null) {\n const node = par[key]!;\n par[key] = skewMerge(this.compare, [node.left, node.right]);\n --this.length;\n return true;\n }\n }\n return false;\n }\n\n *dump(): Iterable {\n for (const node of preOrderTraverse(this.root)) {\n yield node.value;\n }\n }\n\n merge(heap: Heap): this {\n if (heap instanceof SkewHeap) {\n this.root = skewMerge(this.compare, [this.root, clone(heap.root)]);\n this.length += heap.size;\n } else if (heap instanceof BinaryHeap) {\n this.root = skewMerge(this.compare, [this.root, toBinaryTree(heap['array'])!]);\n this.length += heap.size;\n } else {\n this.addAll(heap.dump());\n }\n return this;\n }\n\n peek(): T | undefined {\n return this.root?.value;\n }\n\n pop(): T | undefined {\n if (this.root == null) {\n return undefined;\n }\n const value = this.root.value;\n this.root = skewMerge(this.compare, [this.root.left, this.root.right]);\n --this.length;\n return value;\n }\n\n push(value: T): number {\n this.root = skewMerge(this.compare, [this.root, { value }]);\n return ++this.length;\n }\n\n pushPop(value: T): T {\n this.push(value);\n return this.pop()!;\n }\n\n replace(value: T): T | undefined {\n if (this.root == null) {\n this.root = { value };\n this.length = 1;\n return undefined;\n }\n const out = this.root.value;\n this.root = skewMerge(this.compare, [this.root.left, this.root.right, { value }]);\n return out;\n }\n\n get size(): number {\n return this.length;\n }\n /**\n * Iterate through the heap in sorted order.\n *\n * **Note:** Unexpected behavior can occur if the collection is modified during iteration.\n *\n * @returns An iterator through the heap.\n */\n *[Symbol.iterator](): Iterator {\n if (this.root == null) {\n return;\n }\n const heap = new SkewHeap>((a, b) => this.compare(a.value, b.value), [\n this.root,\n ]);\n do {\n const node = heap.pop()!;\n yield node.value;\n node.left && heap.push(node.left);\n node.right && heap.push(node.right);\n } while (heap.size > 0);\n }\n\n update(curElement: T, newElement: T): boolean {\n if (this.root == null) {\n return false;\n }\n if (this.root.value === curElement) {\n this.root = skewMerge(this.compare, [\n this.root.left,\n this.root.right,\n { value: newElement },\n ]);\n return true;\n }\n for (const par of preOrderTraverse(this.root)) {\n const key: keyof BinaryTreeNode | undefined =\n par.left && par.left.value === curElement\n ? 'left'\n : par.right && par.right.value === curElement\n ? 'right'\n : undefined;\n if (key != null) {\n const node = par[key]!;\n par[key] = undefined;\n this.root = skewMerge(this.compare, [\n this.root,\n node.left,\n node.right,\n { value: newElement },\n ]);\n return true;\n }\n }\n return false;\n }\n}\n","import { LinkedList } from 'src/list';\nimport { BinaryTreeNode } from 'src/tree';\nimport { CompareFn } from '..';\n\n/**\n * @internal\n */\nexport function bubbleUp(index: number, compareFn: CompareFn, array: Array): void {\n const value = array[index];\n\n // Until we reach the top of the heap\n while (index > 0) {\n // Get the parent\n const parentIndex = Math.floor((index + 1) / 2) - 1;\n const parent = array[parentIndex]!;\n\n // If the parent is above or equal to value, the heap is in order\n if (compareFn(parent, value) <= 0) {\n break;\n }\n\n // Swap the parent with value and continue\n array[parentIndex] = value;\n array[index] = parent;\n index = parentIndex;\n }\n}\n/**\n * @internal\n */\nexport function heapify(compareFn: CompareFn, array: T[]): void {\n for (let i = (array.length + 1) >>> 1; i > 0; sinkDown(--i, compareFn, array)) {}\n}\n/**\n * @internal\n */\nexport function sinkDown(index: number, compareFn: CompareFn, array: Array): void {\n const n = array.length;\n const value = array[index];\n do {\n // Compute the left child's index\n let childIndex = 2 * index + 1;\n\n // If no children exist\n if (childIndex >= n) {\n break;\n }\n\n // Decide which child to compare with\n let child = array[childIndex];\n if (childIndex + 1 < n && compareFn(array[childIndex + 1], child) <= 0) {\n child = array[++childIndex]!;\n }\n\n // If value <= child\n if (compareFn(value, child) <= 0) {\n break;\n }\n\n // Swap value and child\n array[index] = child;\n array[childIndex] = value;\n index = childIndex;\n } while (true);\n}\n/**\n * See: https://en.wikipedia.org/wiki/Skew_heap#Merging_two_heaps\n *\n * @param compareFn - A function used to determine the order of the heap.\n *\n * It is expected to return:\n * - A negative value if first argument < second argument\n * - Zero if first argument == second argument\n * - A positive value if first argument > second argument\n * @param heaps - An iterable of heaps to merge\n *\n * @returns The new heap\n */\nexport function skewMerge(\n compareFn: CompareFn,\n heaps: Iterable | undefined>,\n): BinaryTreeNode | undefined {\n // Sanitize inputs\n const list = new LinkedList>();\n for (const node of heaps) {\n if (node != null) {\n list.push(node);\n }\n }\n if (list.size < 2) {\n return list.pop()!;\n }\n\n // Split each heap into subtrees by cutting every path.\n // (From the root node, sever the right node and make the right\n // child its own subtree.) This will result in a set of trees\n // in which the root either only has a left child or no children at all.\n for (const node of list) {\n if (node.right != null) {\n list.push(node.right);\n node.right = undefined;\n }\n }\n\n // Sort the subtrees in descending order based on the\n // value of the root node of each subtree.\n list.sort((a, b) => compareFn(b.value, a.value));\n\n // While there are still multiple subtrees, iteratively recombine\n // the first two (from left to right). If the root of the second-to-first\n // subtree has a left child, swap it to be the right child. Link the root\n // of the last subtree as the left child of the second-to-first subtree.\n let heap = list.shift()!;\n do {\n const next = list.shift()!;\n next.right = next.left;\n next.left = heap;\n heap = next;\n } while (list.size > 0);\n\n return heap;\n}\n","import { CompareFn } from '..';\nimport { List } from './list';\nimport { batch, clamp, cwrap } from './utils';\n\n/**\n * An implementation of the {@link List} interface using an array\n */\nexport class ArrayList implements List {\n /**\n * The array containing every element.\n */\n protected array: Array;\n /**\n * Instantiate the list.\n *\n * @param elements - A set of elements to initialize the list with.\n */\n constructor(elements?: Iterable) {\n this.array = elements ? Array.from(elements) : [];\n }\n\n add(index: number, element: T): number {\n if (index >= 0 && index <= this.size) {\n this.array.splice(index, 0, element);\n }\n return this.size;\n }\n\n addAll(index: number, elements: Iterable): number {\n if (index >= 0 && index <= this.size) {\n for (const items of batch(10000, elements)) {\n this.array.splice(index, 0, ...items);\n index += items.length;\n }\n }\n return this.size;\n }\n\n clear(): void {\n this.array.length = 0;\n }\n\n concat(...lists: Iterable[]): ArrayList {\n const out = new ArrayList(this);\n for (const list of lists) {\n out.addAll(out.size, list);\n }\n return out;\n }\n\n copyWithin(index: number, min?: number, max?: number): this {\n index = cwrap(index ?? 0, 0, this.size);\n min = cwrap(min ?? 0, 0, this.size);\n max = cwrap(max ?? this.size, 0, this.size);\n this.array.copyWithin(index, min, max);\n return this;\n }\n\n fill(element: T, min?: number, max?: number): this {\n min = cwrap(min ?? 0, 0, this.size);\n max = cwrap(max ?? this.size, 0, this.size);\n this.array.fill(element, min, max);\n return this;\n }\n\n get(index: number): T | undefined {\n return index < 0 || index >= this.size ? undefined : this.array[index];\n }\n\n getSet(index: number, callback: (element: T) => T): T | undefined {\n let value: T | undefined = undefined;\n if (index >= 0 && index < this.size) {\n value = this.array[index];\n this.array[index] = callback(value);\n }\n return value;\n }\n\n pop(): T | undefined {\n return this.array.pop();\n }\n\n push(element: T): number {\n return this.array.push(element);\n }\n\n remove(index: number): T | undefined {\n return index < 0 || index >= this.size ? undefined : this.array.splice(index, 1)[0];\n }\n\n reverse(min?: number, max?: number): this {\n min = cwrap(min ?? 0, 0, this.size);\n max = cwrap(max ?? this.size, 0, this.size) - 1;\n while (min < max) {\n const temp = this.array[min];\n this.array[min++] = this.array[max];\n this.array[max--] = temp;\n }\n return this;\n }\n\n set(index: number, element: T): T | undefined {\n let prev: T | undefined = undefined;\n if (index >= 0 && index < this.size) {\n prev = this.array[index];\n this.array[index] = element;\n }\n return prev;\n }\n\n shift(): T | undefined {\n return this.array.shift();\n }\n\n get size(): number {\n return this.array.length;\n }\n\n slice(min?: number, max?: number): ArrayList {\n return new ArrayList(this.array.slice(min, max));\n }\n\n splice(start?: number, count?: number, elements?: Iterable): List {\n start = cwrap(start ?? 0, 0, this.size);\n count = clamp(count ?? this.size, 0, this.size - start);\n const list = new ArrayList(this.array.splice(start, count));\n for (const items of batch(10000, elements ?? [])) {\n this.array.splice(start, 0, ...items);\n start += items.length;\n }\n return list;\n }\n\n sort(compareFn: CompareFn): this {\n this.array.sort(compareFn);\n return this;\n }\n /**\n * Receive an iterator through the list.\n *\n * **Note:** Unexpected behavior can occur if the collection is modified during iteration.\n *\n * @returns An iterator through the list\n */\n [Symbol.iterator](): Iterator {\n return this.array[Symbol.iterator]();\n }\n\n unshift(element: T): number {\n return this.array.unshift(element);\n }\n\n update(callback: (element: T, index: number) => T): this;\n update(min: number | undefined, callback: (element: T, index: number) => T): this;\n update(\n min: number | undefined,\n max: number | undefined,\n callback: (element: T, index: number) => T,\n ): this;\n update(\n min: number | undefined | ((element: T, index: number) => T),\n max?: number | ((element: T, index: number) => T),\n callback?: (element: T, index: number) => T,\n ): this {\n if (callback == null) {\n if (arguments.length < 2) {\n callback = min as (element: T, index: number) => T;\n min = undefined;\n } else {\n callback = max as (element: T, index: number) => T;\n max = undefined;\n }\n }\n min = cwrap((min as number) ?? 0, 0, this.size);\n max = cwrap((max as number) ?? this.size, 0, this.size);\n while (min < max) {\n this.array[min] = callback(this.array[min], min);\n ++min;\n }\n return this;\n }\n\n *view(min?: number, max?: number): Iterable {\n min = cwrap(min ?? 0, 0, this.size);\n\n let len: () => number;\n if (max == null) {\n len = () => this.size;\n } else if (max >= 0) {\n len = () => Math.min(max, this.size);\n } else {\n len = () => this.size + max;\n }\n\n while (min < len()) {\n yield this.array[min++];\n }\n }\n}\n","import { CompareFn } from '..';\nimport { List } from './list';\nimport { clamp, mergeSort, cwrap } from './utils';\n\n/**\n * A doubly-linked node version of the {@link LinkedNode} interface.\n *\n * Each node links to its neighbors on the left (prev) and right (next) of it.\n */\nexport interface DoublyLinkedNode {\n /**\n * A link to the node's next (right) neighbor\n */\n next?: DoublyLinkedNode;\n /**\n * A link to the node's previous (left) neighbor\n */\n prev?: DoublyLinkedNode;\n /**\n * The value of the node\n */\n value: T;\n}\n/**\n * A (circular) doubly-linked list implementation of the {@link List} interface.\n *\n * Operations that index into the list will traverse the list from the beginning or the end, whichever is closer to the specified index.\n */\nexport class DoublyLinkedList implements List {\n /**\n * The number of elements in the list\n */\n protected length: number;\n /**\n * The sentinel node at the fron of the list\n */\n protected root: DoublyLinkedNode;\n /**\n * Instantiate the list.\n *\n * @param elements - A set of elements to initialize the list with.\n */\n constructor(elements?: Iterable) {\n this.length = 0;\n this.root = {} as DoublyLinkedNode;\n this.root.prev = this.root.next = this.root;\n this._addAll(this.root, elements ?? []);\n }\n\n add(index: number, value: T): number {\n if (index < 0 || index > this.length) {\n return this.length;\n }\n const prev = this._get(index - 1);\n const node = { next: prev.next, prev, value };\n prev.next = node;\n node.next!.prev = node;\n return ++this.length;\n }\n\n addAll(index: number, elements: Iterable): number {\n if (index >= 0 && index <= this.length) {\n this._addAll(this._get(index), elements);\n }\n return this.length;\n }\n\n clear(): void {\n this.length = 0;\n this.root.prev = this.root.next = this.root;\n }\n\n concat(...lists: Iterable[]): DoublyLinkedList {\n const out = new DoublyLinkedList(this);\n for (const list of lists) {\n out.addAll(out.size, list);\n }\n return out;\n }\n\n copyWithin(index: number, min?: number, max?: number): this {\n // Check if copying to the same section\n index = cwrap(index, 0, this.length);\n min = cwrap(min ?? 0, 0, this.length);\n if (min === index) {\n return this;\n }\n\n // Check if the section to copy has no length\n max = cwrap(max ?? this.length, 0, this.length);\n max = min + Math.min(max - min, this.length - index);\n if (min >= max) {\n return this;\n }\n\n // Check for overlap edge case\n if (min < index && index < max) {\n let nodeA = this._get(max);\n let nodeB = this._get(index + (max - min));\n do {\n nodeA = nodeA.prev!;\n nodeB = nodeB.prev!;\n nodeB.value = nodeA.value;\n } while (++min < max);\n return this;\n }\n\n // Copy the section to the destination\n let nodeA = this._get(min);\n let nodeB = this._get(index);\n do {\n nodeB.value = nodeA.value;\n nodeA = nodeA.next!;\n nodeB = nodeB.next!;\n } while (++min < max);\n return this;\n }\n\n fill(element: T, min?: number, max?: number): this {\n min = cwrap(min ?? 0, 0, this.length);\n max = cwrap(max ?? this.length, 0, this.length);\n if (min < max) {\n let node = this._get(min);\n do {\n node.value = element;\n node = node.next!;\n } while (++min < max);\n }\n return this;\n }\n\n get(index: number): T | undefined {\n return index < 0 || index >= this.length ? undefined : this._get(index).value;\n }\n\n getSet(index: number, callback: (element: T) => T): T | undefined {\n if (index < 0 || index >= this.length) {\n return undefined;\n }\n const node = this._get(index);\n const value = node.value;\n node.value = callback(node.value);\n return value;\n }\n\n pop(): T | undefined {\n if (this.length < 1) {\n return undefined;\n }\n const tail = this.root.prev!;\n tail.prev!.next = this.root;\n this.root.prev = tail.prev;\n --this.length;\n return tail.value;\n }\n\n push(value: T): number {\n const prev = this.root.prev!;\n const node = { next: this.root, prev, value };\n prev.next = this.root.prev = node;\n return ++this.length;\n }\n\n remove(index: number): T | undefined {\n if (index < 0 || index >= this.length) {\n return undefined;\n }\n const node = this._get(index);\n node.prev!.next = node.next;\n node.next!.prev = node.prev;\n --this.length;\n return node.value;\n }\n\n reverse(min?: number, max?: number): this {\n min = cwrap(min ?? 0, 0, this.length);\n max = cwrap(max ?? this.length, 0, this.length);\n if (max - min < 2) {\n return this;\n }\n const root = this._get(min - 1);\n const tail = root.next!;\n let node = tail;\n do {\n const temp = node.next!;\n node.next = node.prev;\n node.prev = temp;\n root.next = node;\n node = temp;\n } while (++min < max);\n tail.next = node;\n node.prev = tail;\n root.next!.prev = root;\n return this;\n }\n\n set(index: number, element: T): T | undefined {\n if (index < 0 || index >= this.length) {\n return undefined;\n }\n const node = this._get(index);\n const value = node.value;\n node.value = element;\n return value;\n }\n\n shift(): T | undefined {\n if (this.length < 1) {\n return undefined;\n }\n const head = this.root.next!;\n head.next!.prev = this.root;\n this.root.next = head.next;\n --this.length;\n return head.value;\n }\n\n get size(): number {\n return this.length;\n }\n\n slice(min?: number, max?: number): DoublyLinkedList {\n return new DoublyLinkedList(this.view(min, max));\n }\n\n splice(start?: number, count?: number, elements?: Iterable): List {\n start = cwrap(start ?? 0, 0, this.size);\n count = clamp(count ?? this.size, 0, this.size - start);\n\n // If not modifying the list\n const list = new DoublyLinkedList();\n if (elements == null && count < 1) {\n return list;\n }\n\n // Delete elements\n let node = this._get(start);\n while (count-- > 0) {\n list.push(node.value);\n node.prev!.next = node.next!;\n node.next!.prev = node.prev!;\n node = node.next!;\n --this.length;\n }\n\n // Add elements\n this._addAll(node, elements ?? []);\n\n return list;\n }\n\n sort(compareFn: CompareFn): this {\n if (this.length > 1) {\n const [head, tail] = mergeSort(this.root.next!, this.length, true, compareFn);\n this.root.next = head;\n tail.next!.prev = tail;\n }\n return this;\n }\n /**\n * Receive an iterator through the list.\n *\n * **Note:** Unexpected behavior can occur if the collection is modified during iteration.\n *\n * @returns An iterator through the list\n */\n *[Symbol.iterator](): Iterator {\n for (let node = this.root.next!; node !== this.root; node = node.next!) {\n yield node.value;\n }\n }\n\n unshift(value: T): number {\n const head = this.root.next!;\n const node = { next: head, prev: this.root, value };\n this.root.next = head.prev = node;\n return ++this.length;\n }\n\n update(callback: (element: T, index: number) => T): this;\n update(min: number | undefined, callback: (element: T, index: number) => T): this;\n update(\n min: number | undefined,\n max: number | undefined,\n callback: (element: T, index: number) => T,\n ): this;\n update(\n min: number | undefined | ((element: T, index: number) => T),\n max?: number | ((element: T, index: number) => T),\n callback?: (element: T, index: number) => T,\n ): this {\n if (callback == null) {\n if (arguments.length < 2) {\n callback = min as (element: T, index: number) => T;\n min = undefined;\n } else {\n callback = max as (element: T, index: number) => T;\n max = undefined;\n }\n }\n min = cwrap((min as number) ?? 0, 0, this.length);\n max = cwrap((max as number) ?? this.length, 0, this.length);\n if (min < max) {\n let node = this._get(min);\n do {\n node.value = callback(node.value, min);\n node = node.next!;\n } while (++min < max);\n }\n return this;\n }\n\n *view(min?: number, max?: number): Iterable {\n min = cwrap(min ?? 0, 0, this.length);\n\n let len: () => number;\n if (max == null) {\n len = () => this.length;\n } else if (max >= 0) {\n len = () => max;\n } else {\n len = () => this.length + max;\n }\n\n if (min < len()) {\n let node = this._get(min);\n do {\n yield node.value;\n node = node.next!;\n } while (++min < len() && node !== this.root);\n }\n }\n /**\n *\n */\n protected _addAll(next: DoublyLinkedNode, elements: Iterable): void {\n let prev = next.prev!;\n for (const value of elements) {\n const node = { prev, value };\n prev.next = node;\n prev = node;\n ++this.length;\n }\n prev.next = next;\n next.prev = prev;\n }\n /**\n * A helper method to iterate and return the node at the given index.\n *\n * Depending on the index, the list will be traversed from beginning or end; whichever is closest to the specified index.\n *\n * @param index - The index to retrieve\n *\n * @returns The node at the given index\n */\n protected _get(index: number): DoublyLinkedNode {\n let node = this.root;\n if (index < this.length / 2) {\n while (index-- >= 0) {\n node = node.next!;\n }\n } else {\n for (index = this.length - index; index > 0; --index) {\n node = node.prev!;\n }\n }\n return node;\n }\n}\n","import { CompareFn } from '..';\nimport { List } from './list';\nimport { clamp, mergeSort, cwrap } from './utils';\n\n/**\n * A linked node interface.\n *\n * Each node links to its next neighbor.\n */\nexport interface LinkedNode {\n /**\n * A link to the node's neighbor\n */\n next?: LinkedNode;\n /**\n * The value of the node\n */\n value: T;\n}\n/**\n * A (circular) linked list implementation of the {@link List} interface.\n */\nexport class LinkedList implements List {\n /**\n * The number of elements in the list.\n */\n protected length: number;\n /**\n * The sentinel node at the fron of the list.\n */\n protected root: LinkedNode;\n /**\n * The last node of the list.\n */\n protected tail: LinkedNode;\n /**\n * Instantiate the list.\n *\n * @param elements - A set of elements to initialize the list with.\n */\n constructor(elements?: Iterable) {\n this.length = 0;\n this.root = {} as LinkedNode;\n this.root.next = this.root;\n this.tail = this._addAll(this.root, elements ?? []);\n }\n\n add(index: number, value: T): number {\n if (index >= 0 && index < this.length) {\n const prev = this._get(index - 1);\n prev.next = { value, next: prev.next };\n ++this.length;\n } else if (index === this.length) {\n this.push(value);\n }\n return this.length;\n }\n\n addAll(index: number, elements: Iterable): number {\n if (index >= 0 && index < this.length) {\n this._addAll(this._get(index - 1), elements);\n } else if (index === this.length) {\n this.tail = this._addAll(this.tail, elements);\n }\n return this.length;\n }\n\n clear(): void {\n this.length = 0;\n this.tail = this.root.next = this.root;\n }\n\n concat(...lists: Iterable[]): LinkedList {\n const out = new LinkedList(this);\n for (const list of lists) {\n out.addAll(out.size, list);\n }\n return out;\n }\n\n copyWithin(index: number, min?: number, max?: number): this {\n // Check if copying to itself\n index = cwrap(index, 0, this.length);\n min = cwrap(min ?? 0, 0, this.length);\n if (min === index) {\n return this;\n }\n\n // Check if the section to copy has no length\n max = cwrap(max ?? this.length, 0, this.length);\n max = min + Math.min(max - min, this.length - index);\n if (min >= max) {\n return this;\n }\n\n // Copy to earlier in the list\n if (index < min) {\n const node = this._get(index - 1);\n this._copyWithin(this._get(min - index - 1, node), node, max - min);\n return this;\n }\n\n // Copy to later in the list\n if (index > max) {\n const node = this._get(min - 1);\n this._copyWithin(node, this._get(index - min - 1, node), max - min);\n return this;\n }\n\n // Copy to overlapping destination\n const nodeA = this._get(min - 1);\n const nodeC = this._get(max - min - 1, nodeA);\n const nodeD = this._copyWithin(nodeA, nodeC, index - min);\n if (index + (max - min) >= this.length) {\n this.tail = nodeC;\n }\n const temp = nodeA.next;\n nodeA.next = nodeC.next;\n nodeC.next = nodeD.next;\n nodeD.next = temp;\n return this;\n }\n\n fill(element: T, min?: number, max?: number): this {\n min = cwrap(min ?? 0, 0, this.length);\n max = cwrap(max ?? this.length, 0, this.length);\n if (min < max) {\n let node = this._get(min);\n do {\n node.value = element;\n node = node.next!;\n } while (++min < max);\n }\n return this;\n }\n\n get(index: number): T | undefined {\n if (index < 0 || index >= this.length) {\n return undefined;\n }\n return index < this.length - 1 ? this._get(index).value : this.tail.value;\n }\n\n getSet(index: number, callback: (element: T) => T): T | undefined {\n if (index < 0 || index >= this.length) {\n return undefined;\n }\n const node = index < this.length - 1 ? this._get(index) : this.tail;\n const value = node.value;\n node.value = callback(node.value);\n return value;\n }\n\n pop(): T | undefined {\n if (this.length < 1) {\n return undefined;\n }\n const value = this.tail.value;\n this.tail = this._get(this.length - 2);\n this.tail.next = this.root;\n --this.length;\n return value;\n }\n\n push(value: T): number {\n const tail: LinkedNode = { next: this.root, value };\n this.tail.next = tail;\n this.tail = tail;\n return ++this.length;\n }\n\n remove(index: number): T | undefined {\n if (index < 0 || index >= this.length) {\n return undefined;\n }\n const prev = this._get(index - 1);\n const node = prev.next!;\n prev.next = node.next;\n if (index === --this.length) {\n this.tail = prev;\n }\n return node.value;\n }\n\n reverse(min?: number, max?: number): this {\n min = cwrap(min ?? 0, 0, this.length);\n max = cwrap(max ?? this.length, 0, this.length);\n if (max - min < 2) {\n return this;\n }\n const root = this._get(min - 1);\n this.tail = max >= this.length ? root.next! : this.tail;\n const tail = root.next!;\n let prev = tail;\n let node = tail.next!;\n while (++min < max) {\n const next = node.next!;\n node.next = prev;\n prev = node;\n node = next;\n }\n root.next = prev;\n tail.next = node;\n return this;\n }\n\n set(index: number, element: T): T | undefined {\n if (index < 0 || index >= this.length) {\n return undefined;\n }\n const node = this._get(index);\n const value = node.value;\n node.value = element;\n return value;\n }\n\n shift(): T | undefined {\n return this.remove(0);\n }\n\n get size(): number {\n return this.length;\n }\n\n slice(min?: number, max?: number): LinkedList {\n return new LinkedList(this.view(min, max));\n }\n\n splice(start?: number, count?: number, elements?: Iterable): List {\n start = cwrap(start ?? 0, 0, this.size);\n count = clamp(count ?? this.size, 0, this.size - start);\n\n // If not modifying the list\n const deleted = new LinkedList();\n if (elements == null && count < 1) {\n return deleted;\n }\n\n // Delete elements\n let prev = this._get(start - 1);\n const newTail = start + count >= this.size;\n while (count-- > 0) {\n const node = prev.next!;\n deleted.push(node.value);\n prev.next = node.next;\n --this.length;\n }\n\n // Add elements\n prev = this._addAll(prev, elements ?? []);\n this.tail = newTail ? prev : this.tail;\n\n return deleted;\n }\n\n sort(compareFn: CompareFn): this {\n if (this.length > 1) {\n const [head, tail] = mergeSort(this.root.next!, this.length, false, compareFn);\n this.root.next = head;\n this.tail = tail;\n }\n return this;\n }\n /**\n * Receive an iterator through the list.\n *\n * **Note:** Unexpected behavior can occur if the collection is modified during iteration.\n *\n * @returns An iterator through the list\n */\n *[Symbol.iterator](): Iterator {\n for (let node = this.root.next!; node !== this.root; node = node.next!) {\n yield node.value;\n }\n }\n\n unshift(value: T): number {\n return this.add(0, value);\n }\n\n update(callback: (element: T, index: number) => T): this;\n update(min: number | undefined, callback: (element: T, index: number) => T): this;\n update(\n min: number | undefined,\n max: number | undefined,\n callback: (element: T, index: number) => T,\n ): this;\n update(\n min: number | undefined | ((element: T, index: number) => T),\n max?: number | ((element: T, index: number) => T),\n callback?: (element: T, index: number) => T,\n ): this {\n if (callback == null) {\n if (arguments.length < 2) {\n callback = min as (element: T, index: number) => T;\n min = undefined;\n } else {\n callback = max as (element: T, index: number) => T;\n max = undefined;\n }\n }\n min = cwrap((min as number) ?? 0, 0, this.length);\n max = cwrap((max as number) ?? this.length, 0, this.length);\n if (min < max) {\n let node = this._get(min);\n do {\n node.value = callback(node.value, min);\n node = node.next!;\n } while (++min < max);\n }\n return this;\n }\n\n *view(min?: number, max?: number): Iterable {\n min = cwrap(min ?? 0, 0, this.length);\n\n let len: () => number;\n if (max == null) {\n len = () => this.length;\n } else if (max >= 0) {\n len = () => max;\n } else {\n len = () => this.length + max;\n }\n\n if (min < len()) {\n let node = this._get(min);\n do {\n yield node.value;\n node = node.next!;\n } while (++min < len() && node !== this.root);\n }\n }\n\n protected _addAll(prev: LinkedNode, elements: Iterable): LinkedNode {\n const next = prev.next!;\n for (const value of elements) {\n const node = { value };\n prev.next = node;\n prev = node;\n ++this.length;\n }\n prev.next = next;\n return prev;\n }\n /**\n * Copy values from 'from' to 'to'.\n *\n * @param from - The initial node to copy from\n * @param prev - The root of the initial node to copy to\n * @param count - The number of values to copy\n */\n protected _copyWithin(from: LinkedNode, to: LinkedNode, count: number): LinkedNode {\n while (count-- > 0) {\n from = from.next!;\n to = to.next!;\n to.value = from.value;\n }\n return to;\n }\n /**\n * Get the node at the given index.\n *\n * @param index - The index to retrieve\n *\n * @returns The node at the given index\n */\n protected _get(index: number, root: LinkedNode = this.root): LinkedNode {\n let node = root!;\n while (index-- >= 0) {\n node = node.next!;\n }\n return node;\n }\n}\n","import { CompareFn } from '..';\nimport { DoublyLinkedNode } from './doublyLinkedList';\nimport { LinkedNode } from './linkedList';\n\n/**\n * Groups an iterable into batches of a given size.\n *\n * @param size - The maximum batch size\n * @param iterable - The iterable to batch\n *\n * @returns An iterable of batches\n *\n * @internal\n */\nexport function* batch(\n size: number,\n iterable: Iterable,\n): Generator {\n let array: T[] = [];\n for (const value of iterable) {\n if (array.push(value) >= size) {\n size = (yield array) ?? size;\n array = [];\n }\n }\n if (array.length > 0) {\n yield array;\n }\n}\n/**\n * Limits a number to be within a given range.\n *\n * f(x, min, max) = y, where min <= y <= max\n *\n * @param num - The number to clamp\n * @param min - The minimum result value, inclusive\n * @param max - The maximum result value, inclusive\n *\n * @returns The clamped number\n *\n * @internal\n */\nexport function clamp(num: number, min: number, max: number): number {\n return Math.min(max, Math.max(min, num));\n}\n/**\n * Wraps and then clamps a number within a given range.\n *\n * @param num - The number to wrap and then clamp\n * @param min - The minimum result value, inclusive\n * @param max - The wrap pivot and maximum result value, inclusive\n *\n * @returns The crwapped number\n *\n * @internal\n */\nexport function cwrap(num: number, min: number, max: number): number {\n return clamp(wrap(num, max), min, max);\n}\n/**\n * Sorts a list in place.\n *\n * Works on complete lists as well as sublists and circular lists:\n * - Linked lists will keep the link to the next node beyond the sorted section\n * - Doubly linked lists will keep links to the prev and next nodes outside the sorted section\n *\n * @param node - The head of the list\n * @param len - The length of the list beginning from node\n * @param isDoubly - Whether node is a doubly linked node\n * @param compareFn - A function used to determine the order of elements.\n *\n * It is expected to return:\n * - A negative value if first argument < second argument\n * - Zero if first argument == second argument\n * - A positive value if first argument > second argument\n *\n * @returns The new head and tail of the sorted list\n *\n * @internal\n */\nexport function mergeSort>(\n node: Node,\n len: number,\n isDoubly: boolean,\n compareFn: CompareFn,\n): [Node, Node] {\n // Base case\n if (len < 2) {\n return [node, node];\n }\n\n // Split the list into two halves and sort them\n len = len / 2;\n const lens: [number, number] = [Math.ceil(len), Math.floor(len)];\n const heads = mergeSort(node, lens[0], isDoubly, compareFn);\n const tails = mergeSort(heads[1].next as Node, lens[1], isDoubly, compareFn);\n\n // Group the heads and tails together\n node = heads[1];\n heads[1] = tails[0];\n tails[0] = node;\n tails[0].next = tails[1].next;\n\n // Merge the sorted halves\n const prev = (heads[0] as DoublyLinkedNode).prev;\n node = mergeSorted(heads, lens, isDoubly, compareFn);\n isDoubly && ((node as DoublyLinkedNode).prev = prev);\n\n // Return the head and tail\n return [node, tails[+(lens[0] < 1)]];\n}\n/**\n * Merges two sorted lists.\n *\n * @param nodes - The heads of the lists\n * @param lens - The lengths of the lists\n * @param isDoubly - Whether the lists are a doubly linked\n * @param compareFn - A function used to determine the order of elements.\n *\n * It is expected to return:\n * - A negative value if first argument < second argument\n * - Zero if first argument == second argument\n * - A positive value if first argument > second argument\n *\n * @returns The new head of the sorted list\n *\n * @internal\n */\nexport function mergeSorted>(\n heads: [Node, Node],\n lens: [number, number],\n isDoubly: boolean,\n compareFn: CompareFn,\n): Node {\n const root = {} as Node;\n\n let node = root;\n do {\n const index = +(compareFn(heads[0].value, heads[1].value) > 0);\n node.next = heads[index];\n isDoubly && ((node.next as DoublyLinkedNode).prev = node);\n node = node.next as Node;\n heads[index] = node.next as Node;\n --lens[index];\n } while (lens[0] > 0 && lens[1] > 0);\n\n // Add any remaining nodes\n node.next = heads[+(lens[0] < 1)];\n isDoubly && node.next && ((node.next as DoublyLinkedNode).prev = node);\n return root.next as Node;\n}\n/**\n * Moves a given number of spaces forward in a list\n *\n * @param head - The head of the list\n * @param len - The number of spaces to move\n *\n * @returns - The node len spaces ahead from head\n *\n * @internal\n */\nexport function next>(head: Node, len: number): Node {\n while (len-- > 0) {\n head = head.next as Node;\n }\n return head;\n}\n/**\n * Wraps a number around a pivot\n *\n * f(x, min, pivot) = {\n * x, where x >= 0\n * pivot + x, where x < 0\n * }\n *\n * @param num - The number to wrap\n * @param pivot - The number to pivot on\n *\n * @returns - The wrapped number\n *\n * @internal\n */\nexport function wrap(num: number, pivot: number): number {\n return num < 0 ? pivot + num : num;\n}\n","import { Queue } from './queue';\n\n/**\n * An implementation of the {@link Queue} interface using an array\n */\nexport class ArrayQueue implements Queue {\n /**\n * The array containing every element.\n */\n protected array: T[];\n /**\n * Instantiate the queue.\n *\n * @param elements - A set of elements to initialize the queue with.\n */\n constructor(elements?: Iterable) {\n this.array = elements ? Array.from(elements) : [];\n }\n\n clear(): void {\n this.array.length = 0;\n }\n\n dequeue(): T | undefined {\n return this.size < 1 ? undefined : this.array.shift();\n }\n\n enqueue(element: T): number {\n return this.array.push(element);\n }\n\n peek(): T | undefined {\n return this.size < 1 ? undefined : this.array[0];\n }\n\n get size(): number {\n return this.array.length;\n }\n /**\n * Receive an iterator through the queue.\n *\n * **Note:** Unexpected behavior can occur if the collection is modified during iteration.\n *\n * @returns An iterator through the queue\n */\n [Symbol.iterator](): Iterator {\n return this.array[Symbol.iterator]();\n }\n}\n","import { LinkedList, List } from '../list';\nimport { Queue } from './queue';\n\n/**\n * A linked list implementation of the {@link Queue} interface\n */\nexport class LinkedQueue implements Queue {\n /**\n * The list containing every element.\n */\n protected list: List;\n /**\n * Instantiate the queue.\n *\n * @param elements - A set of elements to initialize the queue with.\n */\n constructor(elements?: Iterable) {\n this.list = new LinkedList(elements);\n }\n\n clear(): void {\n this.list.clear();\n }\n\n dequeue(): T | undefined {\n return this.list.shift();\n }\n\n enqueue(element: T): number {\n return this.list.push(element);\n }\n\n peek(): T | undefined {\n return this.list.get(0);\n }\n\n get size(): number {\n return this.list.size;\n }\n /**\n * Receive an iterator through the queue.\n *\n * **Note:** Unexpected behavior can occur if the collection is modified during iteration.\n *\n * @returns An iterator through the queue\n */\n [Symbol.iterator](): Iterator {\n return this.list[Symbol.iterator]();\n }\n}\n","import { Stack } from './stack';\n\n/**\n * An implementation of the {@link Stack} interface using an array\n */\nexport class ArrayStack implements Stack {\n /**\n * The array containing every element.\n */\n protected array: T[];\n /**\n * Instantiate the stack.\n *\n * @param elements - A set of elements to initialize the stack with.\n */\n constructor(elements?: Iterable) {\n this.array = elements ? Array.from(elements) : [];\n }\n\n clear(): void {\n this.array.length = 0;\n }\n\n peek(): T | undefined {\n return this.array[this.array.length - 1];\n }\n\n pop(): T | undefined {\n return this.array.pop();\n }\n\n push(element: T): number {\n return this.array.push(element);\n }\n\n get size(): number {\n return this.array.length;\n }\n /**\n * Receive an iterator through the stack.\n *\n * **Note:** Unexpected behavior can occur if the collection is modified during iteration.\n *\n * @returns An iterator through the stack\n */\n *[Symbol.iterator](): Iterator {\n const array = this.array;\n for (let i = array.length; i > 0; yield array[--i]) {}\n }\n}\n","import { LinkedList, List } from '../list';\nimport { Stack } from './stack';\n\n/**\n * A linked list implementation of the {@link Stack} interface\n */\nexport class LinkedStack implements Stack {\n /**\n * The list containing every element.\n */\n protected list: List;\n /**\n * Instantiate the stack.\n *\n * @param elements - A set of elements to initialize the stack with.\n */\n constructor(elements?: Iterable) {\n this.list = new LinkedList();\n for (const element of elements || []) {\n this.push(element);\n }\n }\n\n clear(): void {\n this.list.clear();\n }\n\n peek(): T | undefined {\n return this.list.get(0);\n }\n\n pop(): T | undefined {\n return this.list.shift();\n }\n\n push(element: T): number {\n return this.list.unshift(element);\n }\n\n get size(): number {\n return this.list.size;\n }\n /**\n * Receive an iterator through the stack.\n *\n * **Note:** Unexpected behavior can occur if the collection is modified during iteration.\n *\n * @returns An iterator through the stack\n */\n [Symbol.iterator](): Iterator {\n return this.list[Symbol.iterator]();\n }\n}\n","// The module cache\nvar __webpack_module_cache__ = {};\n\n// The require function\nfunction __webpack_require__(moduleId) {\n\t// Check if module is in cache\n\tvar cachedModule = __webpack_module_cache__[moduleId];\n\tif (cachedModule !== undefined) {\n\t\treturn cachedModule.exports;\n\t}\n\t// Create a new module (and put it into the cache)\n\tvar module = __webpack_module_cache__[moduleId] = {\n\t\t// no module.id needed\n\t\t// no module.loaded needed\n\t\texports: {}\n\t};\n\n\t// Execute the module function\n\t__webpack_modules__[moduleId](module, module.exports, __webpack_require__);\n\n\t// Return the exports of the module\n\treturn module.exports;\n}\n\n","// getDefaultExport function for compatibility with non-harmony modules\n__webpack_require__.n = (module) => {\n\tvar getter = module && module.__esModule ?\n\t\t() => (module['default']) :\n\t\t() => (module);\n\t__webpack_require__.d(getter, { a: getter });\n\treturn getter;\n};","// define getter functions for harmony exports\n__webpack_require__.d = (exports, definition) => {\n\tfor(var key in definition) {\n\t\tif(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {\n\t\t\tObject.defineProperty(exports, key, { enumerable: true, get: definition[key] });\n\t\t}\n\t}\n};","__webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))","// define __esModule on exports\n__webpack_require__.r = (exports) => {\n\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n\t}\n\tObject.defineProperty(exports, '__esModule', { value: true });\n};"],"sourceRoot":""} \ No newline at end of file diff --git a/docs/README.md b/docs/README.md index 844ad7e..95198bd 100644 --- a/docs/README.md +++ b/docs/README.md @@ -1,6 +1,6 @@ -dastal - v1.3.1 +dastal - v1.4.0 -# dastal - v1.3.1 +# dastal - v1.4.0 ## Table of contents @@ -9,15 +9,62 @@ dastal - v1.3.1 - [ArrayList](classes/arraylist.md) - [ArrayQueue](classes/arrayqueue.md) - [ArrayStack](classes/arraystack.md) +- [BinaryHeap](classes/binaryheap.md) - [DoublyLinkedList](classes/doublylinkedlist.md) - [LinkedList](classes/linkedlist.md) - [LinkedQueue](classes/linkedqueue.md) - [LinkedStack](classes/linkedstack.md) +- [SkewHeap](classes/skewheap.md) ### Interfaces - [DoublyLinkedNode](interfaces/doublylinkednode.md) +- [Heap](interfaces/heap.md) - [LinkedNode](interfaces/linkednode.md) - [List](interfaces/list.md) - [Queue](interfaces/queue.md) +- [Sortable](interfaces/sortable.md) +- [Sorted](interfaces/sorted.md) - [Stack](interfaces/stack.md) + +### Type aliases + +- [CompareFn](README.md#comparefn) + +## Type aliases + +### CompareFn + +Ƭ **CompareFn**: (`a`: T, `b`: T) => *number* + +A function used to determine the order of a set of elements. + +**`param`** The first element + +**`param`** The second element + +**`returns`** +- A negative value if a < b +- Zero if a == b +- A positive value if a > b + +#### Type parameters: + +| Name | +| :------ | +| `T` | + +#### Type declaration: + +▸ (`a`: T, `b`: T): *number* + +#### Parameters: + +| Name | Type | +| :------ | :------ | +| `a` | T | +| `b` | T | + +**Returns:** *number* + +Defined in: [src/index.ts:21](https://github.com/havelessbemore/dastal/blob/dba59a5/src/index.ts#L21) diff --git a/docs/classes/arraylist.md b/docs/classes/arraylist.md index c1ffa99..6d3acf0 100644 --- a/docs/classes/arraylist.md +++ b/docs/classes/arraylist.md @@ -1,4 +1,4 @@ -[dastal - v1.3.1](../README.md) / ArrayList +[dastal - v1.4.0](../README.md) / ArrayList # Class: ArrayList @@ -42,6 +42,7 @@ An implementation of the [List](../interfaces/list.md) interface using an array - [set](arraylist.md#set) - [shift](arraylist.md#shift) - [slice](arraylist.md#slice) +- [sort](arraylist.md#sort) - [splice](arraylist.md#splice) - [unshift](arraylist.md#unshift) - [update](arraylist.md#update) @@ -53,6 +54,8 @@ An implementation of the [List](../interfaces/list.md) interface using an array \+ **new ArrayList**(`elements?`: *Iterable*): [*ArrayList*](arraylist.md) +Instantiate the list. + #### Type parameters: | Name | @@ -61,13 +64,13 @@ An implementation of the [List](../interfaces/list.md) interface using an array #### Parameters: -| Name | Type | -| :------ | :------ | -| `elements?` | *Iterable* | +| Name | Type | Description | +| :------ | :------ | :------ | +| `elements?` | *Iterable* | A set of elements to initialize the list with. | **Returns:** [*ArrayList*](arraylist.md) -Defined in: [src/list/arrayList.ts:11](https://github.com/havelessbemore/dastal/blob/0f470df/src/list/arrayList.ts#L11) +Defined in: [src/list/arrayList.ts:12](https://github.com/havelessbemore/dastal/blob/dba59a5/src/list/arrayList.ts#L12) ## Accessors @@ -81,7 +84,7 @@ The number of elements in this list Implementation of: [List](../interfaces/list.md).[size](../interfaces/list.md#size) -Defined in: [src/list/arrayList.ts:222](https://github.com/havelessbemore/dastal/blob/0f470df/src/list/arrayList.ts#L222) +Defined in: [src/list/arrayList.ts:115](https://github.com/havelessbemore/dastal/blob/dba59a5/src/list/arrayList.ts#L115) ## Methods @@ -99,7 +102,7 @@ An iterator through the list Implementation of: [List](../interfaces/list.md) -Defined in: [src/list/arrayList.ts:280](https://github.com/havelessbemore/dastal/blob/0f470df/src/list/arrayList.ts#L280) +Defined in: [src/list/arrayList.ts:145](https://github.com/havelessbemore/dastal/blob/dba59a5/src/list/arrayList.ts#L145) ___ @@ -111,18 +114,16 @@ Add the element at the specified index. #### Parameters: -| Name | Type | Description | -| :------ | :------ | :------ | -| `index` | *number* | The index to add into | -| `element` | T | The element to add | +| Name | Type | +| :------ | :------ | +| `index` | *number* | +| `element` | T | **Returns:** *number* -The new size of the list - Implementation of: [List](../interfaces/list.md) -Defined in: [src/list/arrayList.ts:24](https://github.com/havelessbemore/dastal/blob/0f470df/src/list/arrayList.ts#L24) +Defined in: [src/list/arrayList.ts:22](https://github.com/havelessbemore/dastal/blob/dba59a5/src/list/arrayList.ts#L22) ___ @@ -134,18 +135,16 @@ Add elements at the specified index. #### Parameters: -| Name | Type | Description | -| :------ | :------ | :------ | -| `index` | *number* | The index to add into | -| `elements` | *Iterable* | - | +| Name | Type | +| :------ | :------ | +| `index` | *number* | +| `elements` | *Iterable* | **Returns:** *number* -The new size of the list - Implementation of: [List](../interfaces/list.md) -Defined in: [src/list/arrayList.ts:38](https://github.com/havelessbemore/dastal/blob/0f470df/src/list/arrayList.ts#L38) +Defined in: [src/list/arrayList.ts:29](https://github.com/havelessbemore/dastal/blob/dba59a5/src/list/arrayList.ts#L29) ___ @@ -159,7 +158,7 @@ Removes all elements Implementation of: [List](../interfaces/list.md) -Defined in: [src/list/arrayList.ts:50](https://github.com/havelessbemore/dastal/blob/0f470df/src/list/arrayList.ts#L50) +Defined in: [src/list/arrayList.ts:39](https://github.com/havelessbemore/dastal/blob/dba59a5/src/list/arrayList.ts#L39) ___ @@ -167,24 +166,19 @@ ___ ▸ **concat**(...`lists`: *Iterable*[]): [*ArrayList*](arraylist.md) -Combines the list with multiple iterables into a new list. -Does not modify the existing list or inputs. +Combines the list with multiple iterables into a new list. Does not modify the existing list or inputs. #### Parameters: -| Name | Type | Description | -| :------ | :------ | :------ | -| `...lists` | *Iterable*[] | — Additional iterables to add to the end of the list. | +| Name | Type | +| :------ | :------ | +| `...lists` | *Iterable*[] | **Returns:** [*ArrayList*](arraylist.md) -A new list consisting of the elements in the list on which -it is called, followed in order by the elements of each argument. It -does not recurse into nested iterable arguments - Implementation of: [List](../interfaces/list.md) -Defined in: [src/list/arrayList.ts:63](https://github.com/havelessbemore/dastal/blob/0f470df/src/list/arrayList.ts#L63) +Defined in: [src/list/arrayList.ts:43](https://github.com/havelessbemore/dastal/blob/dba59a5/src/list/arrayList.ts#L43) ___ @@ -202,19 +196,17 @@ the copied sequence will be trimmed to fit list.size #### Parameters: -| Name | Type | Description | -| :------ | :------ | :------ | -| `index` | *number* | Where to copy the sequence to | -| `min?` | *number* | Where to start copying elements from, inclusive. Defaults to 0 | -| `max?` | *number* | Where to end copying elements from, exclusive. Defaults to list.size | +| Name | Type | +| :------ | :------ | +| `index` | *number* | +| `min?` | *number* | +| `max?` | *number* | **Returns:** [*ArrayList*](arraylist.md) -The list - Implementation of: [List](../interfaces/list.md) -Defined in: [src/list/arrayList.ts:85](https://github.com/havelessbemore/dastal/blob/0f470df/src/list/arrayList.ts#L85) +Defined in: [src/list/arrayList.ts:51](https://github.com/havelessbemore/dastal/blob/dba59a5/src/list/arrayList.ts#L51) ___ @@ -229,19 +221,17 @@ end of the list. For example, -2 refers to the second to last element of the lis #### Parameters: -| Name | Type | Description | -| :------ | :------ | :------ | -| `element` | T | — element to fill list section with | -| `min?` | *number* | Where to start filling the list, inclusive. Defaults to 0 | -| `max?` | *number* | - | +| Name | Type | +| :------ | :------ | +| `element` | T | +| `min?` | *number* | +| `max?` | *number* | **Returns:** [*ArrayList*](arraylist.md) -The list on which this method was called - Implementation of: [List](../interfaces/list.md) -Defined in: [src/list/arrayList.ts:104](https://github.com/havelessbemore/dastal/blob/0f470df/src/list/arrayList.ts#L104) +Defined in: [src/list/arrayList.ts:59](https://github.com/havelessbemore/dastal/blob/dba59a5/src/list/arrayList.ts#L59) ___ @@ -251,22 +241,17 @@ ___ Return the element at the specified index. -A negative index can be used for to indicate an offset from the -end of the list. For example, -2 refers to the second to last element of the list. - #### Parameters: -| Name | Type | Description | -| :------ | :------ | :------ | -| `index` | *number* | The index to retrieve | +| Name | Type | +| :------ | :------ | +| `index` | *number* | **Returns:** *undefined* \| T -The element at the index, or `undefined` if index is invalid - Implementation of: [List](../interfaces/list.md) -Defined in: [src/list/arrayList.ts:120](https://github.com/havelessbemore/dastal/blob/0f470df/src/list/arrayList.ts#L120) +Defined in: [src/list/arrayList.ts:66](https://github.com/havelessbemore/dastal/blob/dba59a5/src/list/arrayList.ts#L66) ___ @@ -276,23 +261,18 @@ ___ Update the element at the specified index. -A negative index can be used to indicate an offset from the -end of the list. For example, -2 refers to the second to last element of the list. - #### Parameters: -| Name | Type | Description | -| :------ | :------ | :------ | -| `index` | *number* | The index to retrieve | -| `callback` | (`element`: T) => T | A function that receives the previous element and returns the new element. The function is only called if the index is valid | +| Name | Type | +| :------ | :------ | +| `index` | *number* | +| `callback` | (`element`: T) => T | **Returns:** *undefined* \| T -The previous element at the index, or `undefined` if index is invalid - Implementation of: [List](../interfaces/list.md) -Defined in: [src/list/arrayList.ts:135](https://github.com/havelessbemore/dastal/blob/0f470df/src/list/arrayList.ts#L135) +Defined in: [src/list/arrayList.ts:70](https://github.com/havelessbemore/dastal/blob/dba59a5/src/list/arrayList.ts#L70) ___ @@ -300,15 +280,13 @@ ___ ▸ **pop**(): *undefined* \| T -Retrieves and removes the end of the list +Retrieves and removes the end of the list. **Returns:** *undefined* \| T -The element at the end of the list, or `undefined` if empty. - Implementation of: [List](../interfaces/list.md) -Defined in: [src/list/arrayList.ts:148](https://github.com/havelessbemore/dastal/blob/0f470df/src/list/arrayList.ts#L148) +Defined in: [src/list/arrayList.ts:79](https://github.com/havelessbemore/dastal/blob/dba59a5/src/list/arrayList.ts#L79) ___ @@ -316,21 +294,19 @@ ___ ▸ **push**(`element`: T): *number* -Inserts the specified element into the end of the list +Inserts the specified value into the end of the list #### Parameters: -| Name | Type | Description | -| :------ | :------ | :------ | -| `element` | T | The element to be inserted | +| Name | Type | +| :------ | :------ | +| `element` | T | **Returns:** *number* -The new size of the list - Implementation of: [List](../interfaces/list.md) -Defined in: [src/list/arrayList.ts:158](https://github.com/havelessbemore/dastal/blob/0f470df/src/list/arrayList.ts#L158) +Defined in: [src/list/arrayList.ts:83](https://github.com/havelessbemore/dastal/blob/dba59a5/src/list/arrayList.ts#L83) ___ @@ -345,17 +321,15 @@ end of the list. For example, -2 refers to the second to last element of the lis #### Parameters: -| Name | Type | Description | -| :------ | :------ | :------ | -| `index` | *number* | The index to remove | +| Name | Type | +| :------ | :------ | +| `index` | *number* | **Returns:** *undefined* \| T -The value at the index, or `undefined` if the index is invalid - Implementation of: [List](../interfaces/list.md) -Defined in: [src/list/arrayList.ts:171](https://github.com/havelessbemore/dastal/blob/0f470df/src/list/arrayList.ts#L171) +Defined in: [src/list/arrayList.ts:87](https://github.com/havelessbemore/dastal/blob/dba59a5/src/list/arrayList.ts#L87) ___ @@ -370,18 +344,16 @@ end of the list. For example, -2 refers to the second to last element of the lis #### Parameters: -| Name | Type | Description | -| :------ | :------ | :------ | -| `min?` | *number* | The beginning index of the specified portion of the list, inclusive. Defaults to 0 | -| `max?` | *number* | The end index of the specified portion of the list, exclusive. Defaults to list.size | +| Name | Type | +| :------ | :------ | +| `min?` | *number* | +| `max?` | *number* | **Returns:** [*ArrayList*](arraylist.md) -a reference to the same list - Implementation of: [List](../interfaces/list.md) -Defined in: [src/list/arrayList.ts:185](https://github.com/havelessbemore/dastal/blob/0f470df/src/list/arrayList.ts#L185) +Defined in: [src/list/arrayList.ts:91](https://github.com/havelessbemore/dastal/blob/dba59a5/src/list/arrayList.ts#L91) ___ @@ -393,18 +365,16 @@ Update the element at the specified index. #### Parameters: -| Name | Type | Description | -| :------ | :------ | :------ | -| `index` | *number* | The index to retrieve | -| `element` | T | The new element to insert at index | +| Name | Type | +| :------ | :------ | +| `index` | *number* | +| `element` | T | **Returns:** *undefined* \| T -The previous element in the index, or undefined if the index is invalid - Implementation of: [List](../interfaces/list.md) -Defined in: [src/list/arrayList.ts:203](https://github.com/havelessbemore/dastal/blob/0f470df/src/list/arrayList.ts#L203) +Defined in: [src/list/arrayList.ts:102](https://github.com/havelessbemore/dastal/blob/dba59a5/src/list/arrayList.ts#L102) ___ @@ -412,15 +382,13 @@ ___ ▸ **shift**(): *undefined* \| T -Retrieves and removes the first element in the list +Retrieves and removes the first element in the list. **Returns:** *undefined* \| T -The element at the front of the list or `undefined` if this list is empty. - Implementation of: [List](../interfaces/list.md) -Defined in: [src/list/arrayList.ts:216](https://github.com/havelessbemore/dastal/blob/0f470df/src/list/arrayList.ts#L216) +Defined in: [src/list/arrayList.ts:111](https://github.com/havelessbemore/dastal/blob/dba59a5/src/list/arrayList.ts#L111) ___ @@ -435,18 +403,36 @@ end of the list. For example, -2 refers to the second to last element of the lis #### Parameters: -| Name | Type | Description | -| :------ | :------ | :------ | -| `min?` | *number* | The beginning index of the specified portion of the list, inclusive. Defaults to 0 | -| `max?` | *number* | The end index of the specified portion of the list, exclusive. Defaults to list.size | +| Name | Type | +| :------ | :------ | +| `min?` | *number* | +| `max?` | *number* | **Returns:** [*ArrayList*](arraylist.md) -A new list with a copy of the indicated section of the original list +Implementation of: [List](../interfaces/list.md) + +Defined in: [src/list/arrayList.ts:119](https://github.com/havelessbemore/dastal/blob/dba59a5/src/list/arrayList.ts#L119) + +___ + +### sort + +▸ **sort**(`compareFn`: [*CompareFn*](../README.md#comparefn)): [*ArrayList*](arraylist.md) + +Sorts the elements in place. + +#### Parameters: + +| Name | Type | +| :------ | :------ | +| `compareFn` | [*CompareFn*](../README.md#comparefn) | + +**Returns:** [*ArrayList*](arraylist.md) Implementation of: [List](../interfaces/list.md) -Defined in: [src/list/arrayList.ts:236](https://github.com/havelessbemore/dastal/blob/0f470df/src/list/arrayList.ts#L236) +Defined in: [src/list/arrayList.ts:134](https://github.com/havelessbemore/dastal/blob/dba59a5/src/list/arrayList.ts#L134) ___ @@ -459,19 +445,17 @@ Returns any deleted elements. #### Parameters: -| Name | Type | Description | -| :------ | :------ | :------ | -| `start?` | *number* | The index from which to start removing elements. Defaults to 0 If > size, start will be set to size. In this case, no element will be deleted but the method can still add elements to the end of the list. If < 0, start will indicate an offset from the end of the list. For example, -2 refers to the second to last element of the list. If < -size, start will be set to 0 | -| `count?` | *number* | The number of elements to remove. Defaults to size - start If >= size - start (that is, if it's >= than the number of elements from start until the end of the list), then all the elements from start until the end of the list will be removed. If <= 0, no elements are removed | -| `elements?` | *Iterable* | The new elements to insert at start. Defaults to none | +| Name | Type | +| :------ | :------ | +| `start?` | *number* | +| `count?` | *number* | +| `elements?` | *Iterable* | **Returns:** [*List*](../interfaces/list.md) -A new list of deleted elements - Implementation of: [List](../interfaces/list.md) -Defined in: [src/list/arrayList.ts:263](https://github.com/havelessbemore/dastal/blob/0f470df/src/list/arrayList.ts#L263) +Defined in: [src/list/arrayList.ts:123](https://github.com/havelessbemore/dastal/blob/dba59a5/src/list/arrayList.ts#L123) ___ @@ -479,21 +463,19 @@ ___ ▸ **unshift**(`element`: T): *number* -Inserts the specified element into the front of the list +Inserts the specified value into the front of the list #### Parameters: -| Name | Type | Description | -| :------ | :------ | :------ | -| `element` | T | The element to be inserted | +| Name | Type | +| :------ | :------ | +| `element` | T | **Returns:** *number* -The new size of the list - Implementation of: [List](../interfaces/list.md) -Defined in: [src/list/arrayList.ts:290](https://github.com/havelessbemore/dastal/blob/0f470df/src/list/arrayList.ts#L290) +Defined in: [src/list/arrayList.ts:149](https://github.com/havelessbemore/dastal/blob/dba59a5/src/list/arrayList.ts#L149) ___ @@ -505,17 +487,15 @@ Update the elements of the list #### Parameters: -| Name | Type | Description | -| :------ | :------ | :------ | -| `callback` | (`element`: T, `index`: *number*) => T | A function called for each index. Returns the new element | +| Name | Type | +| :------ | :------ | +| `callback` | (`element`: T, `index`: *number*) => T | **Returns:** [*ArrayList*](arraylist.md) -The list on which this method was called - Implementation of: [List](../interfaces/list.md) -Defined in: [src/list/arrayList.ts:300](https://github.com/havelessbemore/dastal/blob/0f470df/src/list/arrayList.ts#L300) +Defined in: [src/list/arrayList.ts:153](https://github.com/havelessbemore/dastal/blob/dba59a5/src/list/arrayList.ts#L153) ▸ **update**(`min`: *undefined* \| *number*, `callback`: (`element`: T, `index`: *number*) => T): [*ArrayList*](arraylist.md) @@ -526,18 +506,16 @@ end of the list. For example, -2 refers to the second to last element of the lis #### Parameters: -| Name | Type | Description | -| :------ | :------ | :------ | -| `min` | *undefined* \| *number* | Where to start filling the list, inclusive. Defaults to 0 | -| `callback` | (`element`: T, `index`: *number*) => T | A function called for each index. Returns the new element | +| Name | Type | +| :------ | :------ | +| `min` | *undefined* \| *number* | +| `callback` | (`element`: T, `index`: *number*) => T | **Returns:** [*ArrayList*](arraylist.md) -The list on which this method was called - Implementation of: [List](../interfaces/list.md) -Defined in: [src/list/arrayList.ts:312](https://github.com/havelessbemore/dastal/blob/0f470df/src/list/arrayList.ts#L312) +Defined in: [src/list/arrayList.ts:154](https://github.com/havelessbemore/dastal/blob/dba59a5/src/list/arrayList.ts#L154) ▸ **update**(`min`: *undefined* \| *number*, `max`: *undefined* \| *number*, `callback`: (`element`: T, `index`: *number*) => T): [*ArrayList*](arraylist.md) @@ -548,19 +526,17 @@ end of the list. For example, -2 refers to the second to last element of the lis #### Parameters: -| Name | Type | Description | -| :------ | :------ | :------ | -| `min` | *undefined* \| *number* | Where to start filling the list, inclusive. Defaults to 0 | -| `max` | *undefined* \| *number* | Where to stop filling the list, exclusive. Defaults to list.size | -| `callback` | (`element`: T, `index`: *number*) => T | A function called for each index. Returns the new element | +| Name | Type | +| :------ | :------ | +| `min` | *undefined* \| *number* | +| `max` | *undefined* \| *number* | +| `callback` | (`element`: T, `index`: *number*) => T | **Returns:** [*ArrayList*](arraylist.md) -The list on which this method was called - Implementation of: [List](../interfaces/list.md) -Defined in: [src/list/arrayList.ts:325](https://github.com/havelessbemore/dastal/blob/0f470df/src/list/arrayList.ts#L325) +Defined in: [src/list/arrayList.ts:155](https://github.com/havelessbemore/dastal/blob/dba59a5/src/list/arrayList.ts#L155) ___ @@ -577,15 +553,13 @@ end of the list. For example, -2 refers to the second to last element of the lis #### Parameters: -| Name | Type | Description | -| :------ | :------ | :------ | -| `min?` | *number* | The beginning index of the specified portion of the list, inclusive. Defaults to 0 | -| `max?` | *number* | The end index of the specified portion of the list, exclusive. Defaults to list.size | +| Name | Type | +| :------ | :------ | +| `min?` | *number* | +| `max?` | *number* | **Returns:** *Iterable* -An iterator through the indicated section of the list - Implementation of: [List](../interfaces/list.md) -Defined in: [src/list/arrayList.ts:365](https://github.com/havelessbemore/dastal/blob/0f470df/src/list/arrayList.ts#L365) +Defined in: [src/list/arrayList.ts:183](https://github.com/havelessbemore/dastal/blob/dba59a5/src/list/arrayList.ts#L183) diff --git a/docs/classes/arrayqueue.md b/docs/classes/arrayqueue.md index 3d8739a..d6f42b9 100644 --- a/docs/classes/arrayqueue.md +++ b/docs/classes/arrayqueue.md @@ -1,4 +1,4 @@ -[dastal - v1.3.1](../README.md) / ArrayQueue +[dastal - v1.4.0](../README.md) / ArrayQueue # Class: ArrayQueue @@ -38,6 +38,8 @@ An implementation of the [Queue](../interfaces/queue.md) interface using an arra \+ **new ArrayQueue**(`elements?`: *Iterable*): [*ArrayQueue*](arrayqueue.md) +Instantiate the queue. + #### Type parameters: | Name | @@ -46,13 +48,13 @@ An implementation of the [Queue](../interfaces/queue.md) interface using an arra #### Parameters: -| Name | Type | -| :------ | :------ | -| `elements?` | *Iterable* | +| Name | Type | Description | +| :------ | :------ | :------ | +| `elements?` | *Iterable* | A set of elements to initialize the queue with. | **Returns:** [*ArrayQueue*](arrayqueue.md) -Defined in: [src/queue/arrayQueue.ts:10](https://github.com/havelessbemore/dastal/blob/0f470df/src/queue/arrayQueue.ts#L10) +Defined in: [src/queue/arrayQueue.ts:10](https://github.com/havelessbemore/dastal/blob/dba59a5/src/queue/arrayQueue.ts#L10) ## Accessors @@ -66,7 +68,7 @@ The number of elements in this queue Implementation of: [Queue](../interfaces/queue.md).[size](../interfaces/queue.md#size) -Defined in: [src/queue/arrayQueue.ts:48](https://github.com/havelessbemore/dastal/blob/0f470df/src/queue/arrayQueue.ts#L48) +Defined in: [src/queue/arrayQueue.ts:36](https://github.com/havelessbemore/dastal/blob/dba59a5/src/queue/arrayQueue.ts#L36) ## Methods @@ -84,7 +86,7 @@ An iterator through the queue Implementation of: [Queue](../interfaces/queue.md) -Defined in: [src/queue/arrayQueue.ts:58](https://github.com/havelessbemore/dastal/blob/0f470df/src/queue/arrayQueue.ts#L58) +Defined in: [src/queue/arrayQueue.ts:46](https://github.com/havelessbemore/dastal/blob/dba59a5/src/queue/arrayQueue.ts#L46) ___ @@ -98,7 +100,7 @@ Removes all elements from this queue Implementation of: [Queue](../interfaces/queue.md) -Defined in: [src/queue/arrayQueue.ts:18](https://github.com/havelessbemore/dastal/blob/0f470df/src/queue/arrayQueue.ts#L18) +Defined in: [src/queue/arrayQueue.ts:20](https://github.com/havelessbemore/dastal/blob/dba59a5/src/queue/arrayQueue.ts#L20) ___ @@ -110,11 +112,9 @@ Retrieves and removes the head of this queue **Returns:** *undefined* \| T -The element at the head of the queue or `undefined` if this queue is empty. - Implementation of: [Queue](../interfaces/queue.md) -Defined in: [src/queue/arrayQueue.ts:26](https://github.com/havelessbemore/dastal/blob/0f470df/src/queue/arrayQueue.ts#L26) +Defined in: [src/queue/arrayQueue.ts:24](https://github.com/havelessbemore/dastal/blob/dba59a5/src/queue/arrayQueue.ts#L24) ___ @@ -122,19 +122,19 @@ ___ ▸ **enqueue**(`element`: T): *number* -Inserts the specified element into this queue +Inserts the specified value into this queue #### Parameters: -| Name | Type | Description | -| :------ | :------ | :------ | -| `element` | T | The element to be inserted | +| Name | Type | +| :------ | :------ | +| `element` | T | **Returns:** *number* Implementation of: [Queue](../interfaces/queue.md) -Defined in: [src/queue/arrayQueue.ts:34](https://github.com/havelessbemore/dastal/blob/0f470df/src/queue/arrayQueue.ts#L34) +Defined in: [src/queue/arrayQueue.ts:28](https://github.com/havelessbemore/dastal/blob/dba59a5/src/queue/arrayQueue.ts#L28) ___ @@ -146,8 +146,6 @@ Retrieves, but does not remove, the head of this queue **Returns:** *undefined* \| T -The value at the head of the queue or `undefined` if this queue is empty. - Implementation of: [Queue](../interfaces/queue.md) -Defined in: [src/queue/arrayQueue.ts:42](https://github.com/havelessbemore/dastal/blob/0f470df/src/queue/arrayQueue.ts#L42) +Defined in: [src/queue/arrayQueue.ts:32](https://github.com/havelessbemore/dastal/blob/dba59a5/src/queue/arrayQueue.ts#L32) diff --git a/docs/classes/arraystack.md b/docs/classes/arraystack.md index bec22d7..52a75d7 100644 --- a/docs/classes/arraystack.md +++ b/docs/classes/arraystack.md @@ -1,4 +1,4 @@ -[dastal - v1.3.1](../README.md) / ArrayStack +[dastal - v1.4.0](../README.md) / ArrayStack # Class: ArrayStack @@ -38,6 +38,8 @@ An implementation of the [Stack](../interfaces/stack.md) interface using an arra \+ **new ArrayStack**(`elements?`: *Iterable*): [*ArrayStack*](arraystack.md) +Instantiate the stack. + #### Type parameters: | Name | @@ -46,13 +48,13 @@ An implementation of the [Stack](../interfaces/stack.md) interface using an arra #### Parameters: -| Name | Type | -| :------ | :------ | -| `elements?` | *Iterable* | +| Name | Type | Description | +| :------ | :------ | :------ | +| `elements?` | *Iterable* | A set of elements to initialize the stack with. | **Returns:** [*ArrayStack*](arraystack.md) -Defined in: [src/stack/arrayStack.ts:10](https://github.com/havelessbemore/dastal/blob/0f470df/src/stack/arrayStack.ts#L10) +Defined in: [src/stack/arrayStack.ts:10](https://github.com/havelessbemore/dastal/blob/dba59a5/src/stack/arrayStack.ts#L10) ## Accessors @@ -66,7 +68,7 @@ The number of elements in the stack Implementation of: [Stack](../interfaces/stack.md).[size](../interfaces/stack.md#size) -Defined in: [src/stack/arrayStack.ts:50](https://github.com/havelessbemore/dastal/blob/0f470df/src/stack/arrayStack.ts#L50) +Defined in: [src/stack/arrayStack.ts:36](https://github.com/havelessbemore/dastal/blob/dba59a5/src/stack/arrayStack.ts#L36) ## Methods @@ -84,7 +86,7 @@ An iterator through the stack Implementation of: [Stack](../interfaces/stack.md) -Defined in: [src/stack/arrayStack.ts:60](https://github.com/havelessbemore/dastal/blob/0f470df/src/stack/arrayStack.ts#L60) +Defined in: [src/stack/arrayStack.ts:46](https://github.com/havelessbemore/dastal/blob/dba59a5/src/stack/arrayStack.ts#L46) ___ @@ -98,7 +100,7 @@ Removes all elements from the stack Implementation of: [Stack](../interfaces/stack.md) -Defined in: [src/stack/arrayStack.ts:18](https://github.com/havelessbemore/dastal/blob/0f470df/src/stack/arrayStack.ts#L18) +Defined in: [src/stack/arrayStack.ts:20](https://github.com/havelessbemore/dastal/blob/dba59a5/src/stack/arrayStack.ts#L20) ___ @@ -110,11 +112,9 @@ Retrieves, but does not remove, the top of the stack **Returns:** *undefined* \| T -The element at the top of the stack or `undefined` if empty. - Implementation of: [Stack](../interfaces/stack.md) -Defined in: [src/stack/arrayStack.ts:26](https://github.com/havelessbemore/dastal/blob/0f470df/src/stack/arrayStack.ts#L26) +Defined in: [src/stack/arrayStack.ts:24](https://github.com/havelessbemore/dastal/blob/dba59a5/src/stack/arrayStack.ts#L24) ___ @@ -126,11 +126,9 @@ Retrieves and removes the top of the stack **Returns:** *undefined* \| T -The element at the top of the stack or `undefined` if empty. - Implementation of: [Stack](../interfaces/stack.md) -Defined in: [src/stack/arrayStack.ts:34](https://github.com/havelessbemore/dastal/blob/0f470df/src/stack/arrayStack.ts#L34) +Defined in: [src/stack/arrayStack.ts:28](https://github.com/havelessbemore/dastal/blob/dba59a5/src/stack/arrayStack.ts#L28) ___ @@ -138,18 +136,16 @@ ___ ▸ **push**(`element`: T): *number* -Inserts a element into the stack +Inserts an element into the stack #### Parameters: -| Name | Type | Description | -| :------ | :------ | :------ | -| `element` | T | The element to be inserted | +| Name | Type | +| :------ | :------ | +| `element` | T | **Returns:** *number* -The new size of the stack - Implementation of: [Stack](../interfaces/stack.md) -Defined in: [src/stack/arrayStack.ts:44](https://github.com/havelessbemore/dastal/blob/0f470df/src/stack/arrayStack.ts#L44) +Defined in: [src/stack/arrayStack.ts:32](https://github.com/havelessbemore/dastal/blob/dba59a5/src/stack/arrayStack.ts#L32) diff --git a/docs/classes/binaryheap.md b/docs/classes/binaryheap.md new file mode 100644 index 0000000..14e3cb1 --- /dev/null +++ b/docs/classes/binaryheap.md @@ -0,0 +1,329 @@ +[dastal - v1.4.0](../README.md) / BinaryHeap + +# Class: BinaryHeap + +## Type parameters + +| Name | +| :------ | +| `T` | + +## Implements + +* [*Heap*](../interfaces/heap.md) + +## Table of contents + +### Constructors + +- [constructor](binaryheap.md#constructor) + +### Accessors + +- [size](binaryheap.md#size) + +### Methods + +- [[Symbol.iterator]](binaryheap.md#[symbol.iterator]) +- [addAll](binaryheap.md#addall) +- [clear](binaryheap.md#clear) +- [comparator](binaryheap.md#comparator) +- [contains](binaryheap.md#contains) +- [delete](binaryheap.md#delete) +- [dump](binaryheap.md#dump) +- [merge](binaryheap.md#merge) +- [peek](binaryheap.md#peek) +- [pop](binaryheap.md#pop) +- [push](binaryheap.md#push) +- [pushPop](binaryheap.md#pushpop) +- [replace](binaryheap.md#replace) +- [update](binaryheap.md#update) + +## Constructors + +### constructor + +\+ **new BinaryHeap**(`compareFn`: [*CompareFn*](../README.md#comparefn), `elements?`: *Iterable*): [*BinaryHeap*](binaryheap.md) + +Instantiate a heap. + +#### Type parameters: + +| Name | +| :------ | +| `T` | + +#### Parameters: + +| Name | Type | Description | +| :------ | :------ | :------ | +| `compareFn` | [*CompareFn*](../README.md#comparefn) | The function to determine the order of elements. | +| `elements?` | *Iterable* | A set of elements to initialize the list with. | + +**Returns:** [*BinaryHeap*](binaryheap.md) + +Defined in: [src/heap/binaryHeap.ts:18](https://github.com/havelessbemore/dastal/blob/dba59a5/src/heap/binaryHeap.ts#L18) + +## Accessors + +### size + +• get **size**(): *number* + +The number of elements in the heap. + +**Returns:** *number* + +Implementation of: [Heap](../interfaces/heap.md).[size](../interfaces/heap.md#size) + +Defined in: [src/heap/binaryHeap.ts:170](https://github.com/havelessbemore/dastal/blob/dba59a5/src/heap/binaryHeap.ts#L170) + +## Methods + +### [Symbol.iterator] + +▸ **[Symbol.iterator]**(): *Iterator* + +Iterate through the heap in sorted order. + +**Note:** Unexpected behavior can occur if the collection is modified during iteration. + +**Returns:** *Iterator* + +An iterator through the heap. + +Implementation of: [Heap](../interfaces/heap.md) + +Defined in: [src/heap/binaryHeap.ts:180](https://github.com/havelessbemore/dastal/blob/dba59a5/src/heap/binaryHeap.ts#L180) + +___ + +### addAll + +▸ **addAll**(`elements`: *Iterable*): *number* + +Insert a set of elements into the heap. + +#### Parameters: + +| Name | Type | +| :------ | :------ | +| `elements` | *Iterable* | + +**Returns:** *number* + +Implementation of: [Heap](../interfaces/heap.md) + +Defined in: [src/heap/binaryHeap.ts:31](https://github.com/havelessbemore/dastal/blob/dba59a5/src/heap/binaryHeap.ts#L31) + +___ + +### clear + +▸ **clear**(): *void* + +Remove all elements. + +**Returns:** *void* + +Implementation of: [Heap](../interfaces/heap.md) + +Defined in: [src/heap/binaryHeap.ts:51](https://github.com/havelessbemore/dastal/blob/dba59a5/src/heap/binaryHeap.ts#L51) + +___ + +### comparator + +▸ **comparator**(): [*CompareFn*](../README.md#comparefn) + +**Returns:** [*CompareFn*](../README.md#comparefn) + +Implementation of: [Heap](../interfaces/heap.md) + +Defined in: [src/heap/binaryHeap.ts:55](https://github.com/havelessbemore/dastal/blob/dba59a5/src/heap/binaryHeap.ts#L55) + +___ + +### contains + +▸ **contains**(`element`: T): *boolean* + +Check if an element is in the heap. + +#### Parameters: + +| Name | Type | +| :------ | :------ | +| `element` | T | + +**Returns:** *boolean* + +Implementation of: [Heap](../interfaces/heap.md) + +Defined in: [src/heap/binaryHeap.ts:59](https://github.com/havelessbemore/dastal/blob/dba59a5/src/heap/binaryHeap.ts#L59) + +___ + +### delete + +▸ **delete**(`element`: T): *boolean* + +Delete an element from the heap. + +#### Parameters: + +| Name | Type | +| :------ | :------ | +| `element` | T | + +**Returns:** *boolean* + +Implementation of: [Heap](../interfaces/heap.md) + +Defined in: [src/heap/binaryHeap.ts:63](https://github.com/havelessbemore/dastal/blob/dba59a5/src/heap/binaryHeap.ts#L63) + +___ + +### dump + +▸ **dump**(): *Iterable* + +Iterate through the heap. + +**Note:** Unexpected behavior can occur if the collection is modified during iteration. + +**Returns:** *Iterable* + +Implementation of: [Heap](../interfaces/heap.md) + +Defined in: [src/heap/binaryHeap.ts:83](https://github.com/havelessbemore/dastal/blob/dba59a5/src/heap/binaryHeap.ts#L83) + +___ + +### merge + +▸ **merge**(`heap`: [*Heap*](../interfaces/heap.md)): [*BinaryHeap*](binaryheap.md) + +Join with a different heap and modify the existing heap to +contain elements of both. Does not modify the input. + +#### Parameters: + +| Name | Type | +| :------ | :------ | +| `heap` | [*Heap*](../interfaces/heap.md) | + +**Returns:** [*BinaryHeap*](binaryheap.md) + +Implementation of: [Heap](../interfaces/heap.md) + +Defined in: [src/heap/binaryHeap.ts:89](https://github.com/havelessbemore/dastal/blob/dba59a5/src/heap/binaryHeap.ts#L89) + +___ + +### peek + +▸ **peek**(): *undefined* \| T + +Retrieves, but does not remove, the top of the heap. + +**Returns:** *undefined* \| T + +Implementation of: [Heap](../interfaces/heap.md) + +Defined in: [src/heap/binaryHeap.ts:108](https://github.com/havelessbemore/dastal/blob/dba59a5/src/heap/binaryHeap.ts#L108) + +___ + +### pop + +▸ **pop**(): *undefined* \| T + +Remove the top of the heap (AKA extract). + +**Returns:** *undefined* \| T + +Implementation of: [Heap](../interfaces/heap.md) + +Defined in: [src/heap/binaryHeap.ts:112](https://github.com/havelessbemore/dastal/blob/dba59a5/src/heap/binaryHeap.ts#L112) + +___ + +### push + +▸ **push**(`value`: T): *number* + +Inserts an element into the heap (AKA insert, add). + +#### Parameters: + +| Name | Type | +| :------ | :------ | +| `value` | T | + +**Returns:** *number* + +Implementation of: [Heap](../interfaces/heap.md) + +Defined in: [src/heap/binaryHeap.ts:131](https://github.com/havelessbemore/dastal/blob/dba59a5/src/heap/binaryHeap.ts#L131) + +___ + +### pushPop + +▸ **pushPop**(`value`: T): T + +Insert an element and then remove the top of the heap. + +#### Parameters: + +| Name | Type | +| :------ | :------ | +| `value` | T | + +**Returns:** T + +Implementation of: [Heap](../interfaces/heap.md) + +Defined in: [src/heap/binaryHeap.ts:140](https://github.com/havelessbemore/dastal/blob/dba59a5/src/heap/binaryHeap.ts#L140) + +___ + +### replace + +▸ **replace**(`value`: T): *undefined* \| T + +Remove the top of the heap and then insert a new element (AKA popPush). + +#### Parameters: + +| Name | Type | +| :------ | :------ | +| `value` | T | + +**Returns:** *undefined* \| T + +Implementation of: [Heap](../interfaces/heap.md) + +Defined in: [src/heap/binaryHeap.ts:153](https://github.com/havelessbemore/dastal/blob/dba59a5/src/heap/binaryHeap.ts#L153) + +___ + +### update + +▸ **update**(`curElement`: T, `newElement`: T): *boolean* + +Update a specific element. + +#### Parameters: + +| Name | Type | +| :------ | :------ | +| `curElement` | T | +| `newElement` | T | + +**Returns:** *boolean* + +Implementation of: [Heap](../interfaces/heap.md) + +Defined in: [src/heap/binaryHeap.ts:197](https://github.com/havelessbemore/dastal/blob/dba59a5/src/heap/binaryHeap.ts#L197) diff --git a/docs/classes/doublylinkedlist.md b/docs/classes/doublylinkedlist.md index f2c5954..ef960b6 100644 --- a/docs/classes/doublylinkedlist.md +++ b/docs/classes/doublylinkedlist.md @@ -1,4 +1,4 @@ -[dastal - v1.3.1](../README.md) / DoublyLinkedList +[dastal - v1.4.0](../README.md) / DoublyLinkedList # Class: DoublyLinkedList @@ -44,6 +44,7 @@ Operations that index into the list will traverse the list from the beginning or - [set](doublylinkedlist.md#set) - [shift](doublylinkedlist.md#shift) - [slice](doublylinkedlist.md#slice) +- [sort](doublylinkedlist.md#sort) - [splice](doublylinkedlist.md#splice) - [unshift](doublylinkedlist.md#unshift) - [update](doublylinkedlist.md#update) @@ -55,6 +56,8 @@ Operations that index into the list will traverse the list from the beginning or \+ **new DoublyLinkedList**(`elements?`: *Iterable*): [*DoublyLinkedList*](doublylinkedlist.md) +Instantiate the list. + #### Type parameters: | Name | @@ -63,13 +66,13 @@ Operations that index into the list will traverse the list from the beginning or #### Parameters: -| Name | Type | -| :------ | :------ | -| `elements?` | *Iterable* | +| Name | Type | Description | +| :------ | :------ | :------ | +| `elements?` | *Iterable* | A set of elements to initialize the list with. | **Returns:** [*DoublyLinkedList*](doublylinkedlist.md) -Defined in: [src/list/doublyLinkedList.ts:38](https://github.com/havelessbemore/dastal/blob/0f470df/src/list/doublyLinkedList.ts#L38) +Defined in: [src/list/doublyLinkedList.ts:37](https://github.com/havelessbemore/dastal/blob/dba59a5/src/list/doublyLinkedList.ts#L37) ## Accessors @@ -83,7 +86,7 @@ The number of elements in this list Implementation of: [List](../interfaces/list.md).[size](../interfaces/list.md#size) -Defined in: [src/list/doublyLinkedList.ts:318](https://github.com/havelessbemore/dastal/blob/0f470df/src/list/doublyLinkedList.ts#L318) +Defined in: [src/list/doublyLinkedList.ts:218](https://github.com/havelessbemore/dastal/blob/dba59a5/src/list/doublyLinkedList.ts#L218) ## Methods @@ -101,7 +104,7 @@ An iterator through the list Implementation of: [List](../interfaces/list.md) -Defined in: [src/list/doublyLinkedList.ts:391](https://github.com/havelessbemore/dastal/blob/0f470df/src/list/doublyLinkedList.ts#L391) +Defined in: [src/list/doublyLinkedList.ts:267](https://github.com/havelessbemore/dastal/blob/dba59a5/src/list/doublyLinkedList.ts#L267) ___ @@ -113,18 +116,16 @@ Add the element at the specified index. #### Parameters: -| Name | Type | Description | -| :------ | :------ | :------ | -| `index` | *number* | The index to add into (0 <= index <= size) | -| `value` | T | - | +| Name | Type | +| :------ | :------ | +| `index` | *number* | +| `value` | T | **Returns:** *number* -The new size of the list - Implementation of: [List](../interfaces/list.md) -Defined in: [src/list/doublyLinkedList.ts:54](https://github.com/havelessbemore/dastal/blob/0f470df/src/list/doublyLinkedList.ts#L54) +Defined in: [src/list/doublyLinkedList.ts:50](https://github.com/havelessbemore/dastal/blob/dba59a5/src/list/doublyLinkedList.ts#L50) ___ @@ -136,18 +137,16 @@ Add elements at the specified index. #### Parameters: -| Name | Type | Description | -| :------ | :------ | :------ | -| `index` | *number* | The index to add into (0 <= index <= size) | -| `elements` | *Iterable* | - | +| Name | Type | +| :------ | :------ | +| `index` | *number* | +| `elements` | *Iterable* | **Returns:** *number* -The new size of the list - Implementation of: [List](../interfaces/list.md) -Defined in: [src/list/doublyLinkedList.ts:72](https://github.com/havelessbemore/dastal/blob/0f470df/src/list/doublyLinkedList.ts#L72) +Defined in: [src/list/doublyLinkedList.ts:61](https://github.com/havelessbemore/dastal/blob/dba59a5/src/list/doublyLinkedList.ts#L61) ___ @@ -161,7 +160,7 @@ Removes all elements Implementation of: [List](../interfaces/list.md) -Defined in: [src/list/doublyLinkedList.ts:81](https://github.com/havelessbemore/dastal/blob/0f470df/src/list/doublyLinkedList.ts#L81) +Defined in: [src/list/doublyLinkedList.ts:68](https://github.com/havelessbemore/dastal/blob/dba59a5/src/list/doublyLinkedList.ts#L68) ___ @@ -169,24 +168,19 @@ ___ ▸ **concat**(...`lists`: *Iterable*[]): [*DoublyLinkedList*](doublylinkedlist.md) -Combines the list with multiple iterables into a new list. -Does not modify the existing list or inputs. +Combines the list with multiple iterables into a new list. Does not modify the existing list or inputs. #### Parameters: -| Name | Type | Description | -| :------ | :------ | :------ | -| `...lists` | *Iterable*[] | — Additional iterables to add to the end of the list. | +| Name | Type | +| :------ | :------ | +| `...lists` | *Iterable*[] | **Returns:** [*DoublyLinkedList*](doublylinkedlist.md) -A new list consisting of the elements in the list on which -it is called, followed in order by the elements of each argument. It -does not recurse into nested iterable arguments - Implementation of: [List](../interfaces/list.md) -Defined in: [src/list/doublyLinkedList.ts:95](https://github.com/havelessbemore/dastal/blob/0f470df/src/list/doublyLinkedList.ts#L95) +Defined in: [src/list/doublyLinkedList.ts:73](https://github.com/havelessbemore/dastal/blob/dba59a5/src/list/doublyLinkedList.ts#L73) ___ @@ -204,19 +198,17 @@ the copied sequence will be trimmed to fit list.size #### Parameters: -| Name | Type | Description | -| :------ | :------ | :------ | -| `index` | *number* | Where to copy the sequence to | -| `min?` | *number* | Where to start copying elements from, inclusive. Defaults to 0 | -| `max?` | *number* | Where to end copying elements from, exclusive. Defaults to list.size | +| Name | Type | +| :------ | :------ | +| `index` | *number* | +| `min?` | *number* | +| `max?` | *number* | **Returns:** [*DoublyLinkedList*](doublylinkedlist.md) -The list - Implementation of: [List](../interfaces/list.md) -Defined in: [src/list/doublyLinkedList.ts:117](https://github.com/havelessbemore/dastal/blob/0f470df/src/list/doublyLinkedList.ts#L117) +Defined in: [src/list/doublyLinkedList.ts:81](https://github.com/havelessbemore/dastal/blob/dba59a5/src/list/doublyLinkedList.ts#L81) ___ @@ -231,19 +223,17 @@ end of the list. For example, -2 refers to the second to last element of the lis #### Parameters: -| Name | Type | Description | -| :------ | :------ | :------ | -| `element` | T | — element to fill list section with | -| `min?` | *number* | Where to start filling the list, inclusive. Defaults to 0 | -| `max?` | *number* | - | +| Name | Type | +| :------ | :------ | +| `element` | T | +| `min?` | *number* | +| `max?` | *number* | **Returns:** [*DoublyLinkedList*](doublylinkedlist.md) -The list on which this method was called - Implementation of: [List](../interfaces/list.md) -Defined in: [src/list/doublyLinkedList.ts:166](https://github.com/havelessbemore/dastal/blob/0f470df/src/list/doublyLinkedList.ts#L166) +Defined in: [src/list/doublyLinkedList.ts:119](https://github.com/havelessbemore/dastal/blob/dba59a5/src/list/doublyLinkedList.ts#L119) ___ @@ -255,17 +245,15 @@ Return the element at the specified index. #### Parameters: -| Name | Type | Description | -| :------ | :------ | :------ | -| `index` | *number* | The index to retrieve (0 <= index < size) | +| Name | Type | +| :------ | :------ | +| `index` | *number* | **Returns:** *undefined* \| T -The element at the index, or `undefined` if index is invalid - Implementation of: [List](../interfaces/list.md) -Defined in: [src/list/doublyLinkedList.ts:185](https://github.com/havelessbemore/dastal/blob/0f470df/src/list/doublyLinkedList.ts#L185) +Defined in: [src/list/doublyLinkedList.ts:132](https://github.com/havelessbemore/dastal/blob/dba59a5/src/list/doublyLinkedList.ts#L132) ___ @@ -277,18 +265,16 @@ Update the element at the specified index. #### Parameters: -| Name | Type | Description | -| :------ | :------ | :------ | -| `index` | *number* | The index to retrieve (0 <= index < size) | -| `callback` | (`element`: T) => T | A function that receives the previous element and returns the new element. The function is only called if the index is valid | +| Name | Type | +| :------ | :------ | +| `index` | *number* | +| `callback` | (`element`: T) => T | **Returns:** *undefined* \| T -The previous element at the index, or `undefined` if index is invalid - Implementation of: [List](../interfaces/list.md) -Defined in: [src/list/doublyLinkedList.ts:197](https://github.com/havelessbemore/dastal/blob/0f470df/src/list/doublyLinkedList.ts#L197) +Defined in: [src/list/doublyLinkedList.ts:136](https://github.com/havelessbemore/dastal/blob/dba59a5/src/list/doublyLinkedList.ts#L136) ___ @@ -296,15 +282,13 @@ ___ ▸ **pop**(): *undefined* \| T -Retrieves and removes the end of the list +Retrieves and removes the end of the list. **Returns:** *undefined* \| T -The element at the end of the list, or `undefined` if empty. - Implementation of: [List](../interfaces/list.md) -Defined in: [src/list/doublyLinkedList.ts:211](https://github.com/havelessbemore/dastal/blob/0f470df/src/list/doublyLinkedList.ts#L211) +Defined in: [src/list/doublyLinkedList.ts:146](https://github.com/havelessbemore/dastal/blob/dba59a5/src/list/doublyLinkedList.ts#L146) ___ @@ -312,7 +296,7 @@ ___ ▸ **push**(`value`: T): *number* -Inserts the specified element into the end of the list +Inserts the specified value into the end of the list #### Parameters: @@ -322,11 +306,9 @@ Inserts the specified element into the end of the list **Returns:** *number* -`true` upon success, otherwise `false` - Implementation of: [List](../interfaces/list.md) -Defined in: [src/list/doublyLinkedList.ts:228](https://github.com/havelessbemore/dastal/blob/0f470df/src/list/doublyLinkedList.ts#L228) +Defined in: [src/list/doublyLinkedList.ts:157](https://github.com/havelessbemore/dastal/blob/dba59a5/src/list/doublyLinkedList.ts#L157) ___ @@ -336,19 +318,20 @@ ___ Retrieves and removes the element at the given index. +A negative index can be used to indicate an offset from the +end of the list. For example, -2 refers to the second to last element of the list. + #### Parameters: -| Name | Type | Description | -| :------ | :------ | :------ | -| `index` | *number* | The index to remove (0 <= index < size) | +| Name | Type | +| :------ | :------ | +| `index` | *number* | **Returns:** *undefined* \| T -The value at the index, or `undefined` if the index is invalid - Implementation of: [List](../interfaces/list.md) -Defined in: [src/list/doublyLinkedList.ts:241](https://github.com/havelessbemore/dastal/blob/0f470df/src/list/doublyLinkedList.ts#L241) +Defined in: [src/list/doublyLinkedList.ts:164](https://github.com/havelessbemore/dastal/blob/dba59a5/src/list/doublyLinkedList.ts#L164) ___ @@ -363,18 +346,16 @@ end of the list. For example, -2 refers to the second to last element of the lis #### Parameters: -| Name | Type | Description | -| :------ | :------ | :------ | -| `min?` | *number* | The beginning index of the specified portion of the list, inclusive. Defaults to 0 | -| `max?` | *number* | The end index of the specified portion of the list, exclusive. Defaults to list.size | +| Name | Type | +| :------ | :------ | +| `min?` | *number* | +| `max?` | *number* | **Returns:** [*DoublyLinkedList*](doublylinkedlist.md) -a reference to the same list - Implementation of: [List](../interfaces/list.md) -Defined in: [src/list/doublyLinkedList.ts:262](https://github.com/havelessbemore/dastal/blob/0f470df/src/list/doublyLinkedList.ts#L262) +Defined in: [src/list/doublyLinkedList.ts:175](https://github.com/havelessbemore/dastal/blob/dba59a5/src/list/doublyLinkedList.ts#L175) ___ @@ -386,18 +367,16 @@ Update the element at the specified index. #### Parameters: -| Name | Type | Description | -| :------ | :------ | :------ | -| `index` | *number* | The index to retrieve (0 <= index < size) | -| `element` | T | The new element to insert at index | +| Name | Type | +| :------ | :------ | +| `index` | *number* | +| `element` | T | **Returns:** *undefined* \| T -The previous element in the index, or undefined if the index is invalid - Implementation of: [List](../interfaces/list.md) -Defined in: [src/list/doublyLinkedList.ts:291](https://github.com/havelessbemore/dastal/blob/0f470df/src/list/doublyLinkedList.ts#L291) +Defined in: [src/list/doublyLinkedList.ts:197](https://github.com/havelessbemore/dastal/blob/dba59a5/src/list/doublyLinkedList.ts#L197) ___ @@ -405,15 +384,13 @@ ___ ▸ **shift**(): *undefined* \| T -Retrieves and removes the first element in the list +Retrieves and removes the first element in the list. **Returns:** *undefined* \| T -The element at the front of the list or `undefined` if this list is empty. - Implementation of: [List](../interfaces/list.md) -Defined in: [src/list/doublyLinkedList.ts:305](https://github.com/havelessbemore/dastal/blob/0f470df/src/list/doublyLinkedList.ts#L305) +Defined in: [src/list/doublyLinkedList.ts:207](https://github.com/havelessbemore/dastal/blob/dba59a5/src/list/doublyLinkedList.ts#L207) ___ @@ -428,18 +405,36 @@ end of the list. For example, -2 refers to the second to last element of the lis #### Parameters: -| Name | Type | Description | -| :------ | :------ | :------ | -| `min?` | *number* | The beginning index of the specified portion of the list, inclusive. Defaults to 0 | -| `max?` | *number* | The end index of the specified portion of the list, exclusive. Defaults to list.size | +| Name | Type | +| :------ | :------ | +| `min?` | *number* | +| `max?` | *number* | **Returns:** [*DoublyLinkedList*](doublylinkedlist.md) -A new list with a copy of the indicated section of the original list +Implementation of: [List](../interfaces/list.md) + +Defined in: [src/list/doublyLinkedList.ts:222](https://github.com/havelessbemore/dastal/blob/dba59a5/src/list/doublyLinkedList.ts#L222) + +___ + +### sort + +▸ **sort**(`compareFn`: [*CompareFn*](../README.md#comparefn)): [*DoublyLinkedList*](doublylinkedlist.md) + +Sorts the elements in place. + +#### Parameters: + +| Name | Type | +| :------ | :------ | +| `compareFn` | [*CompareFn*](../README.md#comparefn) | + +**Returns:** [*DoublyLinkedList*](doublylinkedlist.md) Implementation of: [List](../interfaces/list.md) -Defined in: [src/list/doublyLinkedList.ts:332](https://github.com/havelessbemore/dastal/blob/0f470df/src/list/doublyLinkedList.ts#L332) +Defined in: [src/list/doublyLinkedList.ts:252](https://github.com/havelessbemore/dastal/blob/dba59a5/src/list/doublyLinkedList.ts#L252) ___ @@ -452,19 +447,17 @@ Returns any deleted elements. #### Parameters: -| Name | Type | Description | -| :------ | :------ | :------ | -| `start?` | *number* | The index from which to start removing elements. Defaults to 0 If > size, start will be set to size. In this case, no element will be deleted but the method can still add elements to the end of the list. If < 0, start will indicate an offset from the end of the list. For example, -2 refers to the second to last element of the list. If < -size, start will be set to 0 | -| `count?` | *number* | The number of elements to remove. Defaults to size - start If >= size - start (that is, if it's >= than the number of elements from start until the end of the list), then all the elements from start until the end of the list will be removed. If <= 0, no elements are removed | -| `elements?` | *Iterable* | The new elements to insert at start. Defaults to none | +| Name | Type | +| :------ | :------ | +| `start?` | *number* | +| `count?` | *number* | +| `elements?` | *Iterable* | **Returns:** [*List*](../interfaces/list.md) -A new list of deleted elements - Implementation of: [List](../interfaces/list.md) -Defined in: [src/list/doublyLinkedList.ts:359](https://github.com/havelessbemore/dastal/blob/0f470df/src/list/doublyLinkedList.ts#L359) +Defined in: [src/list/doublyLinkedList.ts:226](https://github.com/havelessbemore/dastal/blob/dba59a5/src/list/doublyLinkedList.ts#L226) ___ @@ -472,7 +465,7 @@ ___ ▸ **unshift**(`value`: T): *number* -Inserts the specified element into the front of the list +Inserts the specified value into the front of the list #### Parameters: @@ -482,11 +475,9 @@ Inserts the specified element into the front of the list **Returns:** *number* -`true` upon success, otherwise `false` - Implementation of: [List](../interfaces/list.md) -Defined in: [src/list/doublyLinkedList.ts:403](https://github.com/havelessbemore/dastal/blob/0f470df/src/list/doublyLinkedList.ts#L403) +Defined in: [src/list/doublyLinkedList.ts:273](https://github.com/havelessbemore/dastal/blob/dba59a5/src/list/doublyLinkedList.ts#L273) ___ @@ -498,17 +489,15 @@ Update the elements of the list #### Parameters: -| Name | Type | Description | -| :------ | :------ | :------ | -| `callback` | (`element`: T, `index`: *number*) => T | A function called for each index. Returns the new element | +| Name | Type | +| :------ | :------ | +| `callback` | (`element`: T, `index`: *number*) => T | **Returns:** [*DoublyLinkedList*](doublylinkedlist.md) -The list on which this method was called - Implementation of: [List](../interfaces/list.md) -Defined in: [src/list/doublyLinkedList.ts:416](https://github.com/havelessbemore/dastal/blob/0f470df/src/list/doublyLinkedList.ts#L416) +Defined in: [src/list/doublyLinkedList.ts:280](https://github.com/havelessbemore/dastal/blob/dba59a5/src/list/doublyLinkedList.ts#L280) ▸ **update**(`min`: *undefined* \| *number*, `callback`: (`element`: T, `index`: *number*) => T): [*DoublyLinkedList*](doublylinkedlist.md) @@ -519,18 +508,16 @@ end of the list. For example, -2 refers to the second to last element of the lis #### Parameters: -| Name | Type | Description | -| :------ | :------ | :------ | -| `min` | *undefined* \| *number* | Where to start filling the list, inclusive. Defaults to 0 | -| `callback` | (`element`: T, `index`: *number*) => T | A function called for each index. Returns the new element | +| Name | Type | +| :------ | :------ | +| `min` | *undefined* \| *number* | +| `callback` | (`element`: T, `index`: *number*) => T | **Returns:** [*DoublyLinkedList*](doublylinkedlist.md) -The list on which this method was called - Implementation of: [List](../interfaces/list.md) -Defined in: [src/list/doublyLinkedList.ts:428](https://github.com/havelessbemore/dastal/blob/0f470df/src/list/doublyLinkedList.ts#L428) +Defined in: [src/list/doublyLinkedList.ts:281](https://github.com/havelessbemore/dastal/blob/dba59a5/src/list/doublyLinkedList.ts#L281) ▸ **update**(`min`: *undefined* \| *number*, `max`: *undefined* \| *number*, `callback`: (`element`: T, `index`: *number*) => T): [*DoublyLinkedList*](doublylinkedlist.md) @@ -541,19 +528,17 @@ end of the list. For example, -2 refers to the second to last element of the lis #### Parameters: -| Name | Type | Description | -| :------ | :------ | :------ | -| `min` | *undefined* \| *number* | Where to start filling the list, inclusive. Defaults to 0 | -| `max` | *undefined* \| *number* | Where to stop filling the list, exclusive. Defaults to list.size | -| `callback` | (`element`: T, `index`: *number*) => T | A function called for each index. Returns the new element | +| Name | Type | +| :------ | :------ | +| `min` | *undefined* \| *number* | +| `max` | *undefined* \| *number* | +| `callback` | (`element`: T, `index`: *number*) => T | **Returns:** [*DoublyLinkedList*](doublylinkedlist.md) -The list on which this method was called - Implementation of: [List](../interfaces/list.md) -Defined in: [src/list/doublyLinkedList.ts:441](https://github.com/havelessbemore/dastal/blob/0f470df/src/list/doublyLinkedList.ts#L441) +Defined in: [src/list/doublyLinkedList.ts:282](https://github.com/havelessbemore/dastal/blob/dba59a5/src/list/doublyLinkedList.ts#L282) ___ @@ -570,15 +555,13 @@ end of the list. For example, -2 refers to the second to last element of the lis #### Parameters: -| Name | Type | Description | -| :------ | :------ | :------ | -| `min?` | *number* | The beginning index of the specified portion of the list, inclusive. Defaults to 0 | -| `max?` | *number* | The end index of the specified portion of the list, exclusive. Defaults to list.size | +| Name | Type | +| :------ | :------ | +| `min?` | *number* | +| `max?` | *number* | **Returns:** *Iterable* -An iterator through the indicated section of the list - Implementation of: [List](../interfaces/list.md) -Defined in: [src/list/doublyLinkedList.ts:484](https://github.com/havelessbemore/dastal/blob/0f470df/src/list/doublyLinkedList.ts#L484) +Defined in: [src/list/doublyLinkedList.ts:313](https://github.com/havelessbemore/dastal/blob/dba59a5/src/list/doublyLinkedList.ts#L313) diff --git a/docs/classes/linkedlist.md b/docs/classes/linkedlist.md index 5b27a69..d632236 100644 --- a/docs/classes/linkedlist.md +++ b/docs/classes/linkedlist.md @@ -1,4 +1,4 @@ -[dastal - v1.3.1](../README.md) / LinkedList +[dastal - v1.4.0](../README.md) / LinkedList # Class: LinkedList @@ -27,7 +27,6 @@ A (circular) linked list implementation of the [List](../interfaces/list.md) int ### Methods - [[Symbol.iterator]](linkedlist.md#[symbol.iterator]) -- [\_addAll](linkedlist.md#_addall) - [add](linkedlist.md#add) - [addAll](linkedlist.md#addall) - [clear](linkedlist.md#clear) @@ -43,6 +42,7 @@ A (circular) linked list implementation of the [List](../interfaces/list.md) int - [set](linkedlist.md#set) - [shift](linkedlist.md#shift) - [slice](linkedlist.md#slice) +- [sort](linkedlist.md#sort) - [splice](linkedlist.md#splice) - [unshift](linkedlist.md#unshift) - [update](linkedlist.md#update) @@ -54,6 +54,8 @@ A (circular) linked list implementation of the [List](../interfaces/list.md) int \+ **new LinkedList**(`elements?`: *Iterable*): [*LinkedList*](linkedlist.md) +Instantiate the list. + #### Type parameters: | Name | @@ -62,13 +64,13 @@ A (circular) linked list implementation of the [List](../interfaces/list.md) int #### Parameters: -| Name | Type | -| :------ | :------ | -| `elements?` | *Iterable* | +| Name | Type | Description | +| :------ | :------ | :------ | +| `elements?` | *Iterable* | A set of elements to initialize the list with. | **Returns:** [*LinkedList*](linkedlist.md) -Defined in: [src/list/linkedList.ts:34](https://github.com/havelessbemore/dastal/blob/0f470df/src/list/linkedList.ts#L34) +Defined in: [src/list/linkedList.ts:35](https://github.com/havelessbemore/dastal/blob/dba59a5/src/list/linkedList.ts#L35) ## Accessors @@ -82,7 +84,7 @@ The number of elements in this list Implementation of: [List](../interfaces/list.md).[size](../interfaces/list.md#size) -Defined in: [src/list/linkedList.ts:319](https://github.com/havelessbemore/dastal/blob/0f470df/src/list/linkedList.ts#L319) +Defined in: [src/list/linkedList.ts:221](https://github.com/havelessbemore/dastal/blob/dba59a5/src/list/linkedList.ts#L221) ## Methods @@ -100,24 +102,7 @@ An iterator through the list Implementation of: [List](../interfaces/list.md) -Defined in: [src/list/linkedList.ts:393](https://github.com/havelessbemore/dastal/blob/0f470df/src/list/linkedList.ts#L393) - -___ - -### \_addAll - -▸ `Protected`**_addAll**(`prev`: [*LinkedNode*](../interfaces/linkednode.md), `elements`: *Iterable*): [*LinkedNode*](../interfaces/linkednode.md) - -#### Parameters: - -| Name | Type | -| :------ | :------ | -| `prev` | [*LinkedNode*](../interfaces/linkednode.md) | -| `elements` | *Iterable* | - -**Returns:** [*LinkedNode*](../interfaces/linkednode.md) - -Defined in: [src/list/linkedList.ts:503](https://github.com/havelessbemore/dastal/blob/0f470df/src/list/linkedList.ts#L503) +Defined in: [src/list/linkedList.ts:271](https://github.com/havelessbemore/dastal/blob/dba59a5/src/list/linkedList.ts#L271) ___ @@ -129,18 +114,16 @@ Add the element at the specified index. #### Parameters: -| Name | Type | Description | -| :------ | :------ | :------ | -| `index` | *number* | The index to add into (0 <= index <= size) | -| `value` | T | - | +| Name | Type | +| :------ | :------ | +| `index` | *number* | +| `value` | T | **Returns:** *number* -The new size of the list - Implementation of: [List](../interfaces/list.md) -Defined in: [src/list/linkedList.ts:50](https://github.com/havelessbemore/dastal/blob/0f470df/src/list/linkedList.ts#L50) +Defined in: [src/list/linkedList.ts:48](https://github.com/havelessbemore/dastal/blob/dba59a5/src/list/linkedList.ts#L48) ___ @@ -152,18 +135,16 @@ Add elements at the specified index. #### Parameters: -| Name | Type | Description | -| :------ | :------ | :------ | -| `index` | *number* | The index to add into (0 <= index <= size) | -| `elements` | *Iterable* | - | +| Name | Type | +| :------ | :------ | +| `index` | *number* | +| `elements` | *Iterable* | **Returns:** *number* -The new size of the list - Implementation of: [List](../interfaces/list.md) -Defined in: [src/list/linkedList.ts:68](https://github.com/havelessbemore/dastal/blob/0f470df/src/list/linkedList.ts#L68) +Defined in: [src/list/linkedList.ts:59](https://github.com/havelessbemore/dastal/blob/dba59a5/src/list/linkedList.ts#L59) ___ @@ -177,7 +158,7 @@ Removes all elements Implementation of: [List](../interfaces/list.md) -Defined in: [src/list/linkedList.ts:79](https://github.com/havelessbemore/dastal/blob/0f470df/src/list/linkedList.ts#L79) +Defined in: [src/list/linkedList.ts:68](https://github.com/havelessbemore/dastal/blob/dba59a5/src/list/linkedList.ts#L68) ___ @@ -185,24 +166,19 @@ ___ ▸ **concat**(...`lists`: *Iterable*[]): [*LinkedList*](linkedlist.md) -Combines the list with multiple iterables into a new list. -Does not modify the existing list or inputs. +Combines the list with multiple iterables into a new list. Does not modify the existing list or inputs. #### Parameters: -| Name | Type | Description | -| :------ | :------ | :------ | -| `...lists` | *Iterable*[] | — Additional iterables to add to the end of the list. | +| Name | Type | +| :------ | :------ | +| `...lists` | *Iterable*[] | **Returns:** [*LinkedList*](linkedlist.md) -A new list consisting of the elements in the list on which -it is called, followed in order by the elements of each argument. It -does not recurse into nested iterable arguments - Implementation of: [List](../interfaces/list.md) -Defined in: [src/list/linkedList.ts:93](https://github.com/havelessbemore/dastal/blob/0f470df/src/list/linkedList.ts#L93) +Defined in: [src/list/linkedList.ts:73](https://github.com/havelessbemore/dastal/blob/dba59a5/src/list/linkedList.ts#L73) ___ @@ -220,19 +196,17 @@ the copied sequence will be trimmed to fit list.size #### Parameters: -| Name | Type | Description | -| :------ | :------ | :------ | -| `index` | *number* | Where to copy the sequence to | -| `min?` | *number* | Where to start copying elements from, inclusive. Defaults to 0 | -| `max?` | *number* | Where to end copying elements from, exclusive. Defaults to list.size | +| Name | Type | +| :------ | :------ | +| `index` | *number* | +| `min?` | *number* | +| `max?` | *number* | **Returns:** [*LinkedList*](linkedlist.md) -The list - Implementation of: [List](../interfaces/list.md) -Defined in: [src/list/linkedList.ts:115](https://github.com/havelessbemore/dastal/blob/0f470df/src/list/linkedList.ts#L115) +Defined in: [src/list/linkedList.ts:81](https://github.com/havelessbemore/dastal/blob/dba59a5/src/list/linkedList.ts#L81) ___ @@ -247,19 +221,17 @@ end of the list. For example, -2 refers to the second to last element of the lis #### Parameters: -| Name | Type | Description | -| :------ | :------ | :------ | -| `element` | T | — element to fill list section with | -| `min?` | *number* | Where to start filling the list, inclusive. Defaults to 0 | -| `max?` | *number* | - | +| Name | Type | +| :------ | :------ | +| `element` | T | +| `min?` | *number* | +| `max?` | *number* | **Returns:** [*LinkedList*](linkedlist.md) -The list on which this method was called - Implementation of: [List](../interfaces/list.md) -Defined in: [src/list/linkedList.ts:169](https://github.com/havelessbemore/dastal/blob/0f470df/src/list/linkedList.ts#L169) +Defined in: [src/list/linkedList.ts:124](https://github.com/havelessbemore/dastal/blob/dba59a5/src/list/linkedList.ts#L124) ___ @@ -271,17 +243,15 @@ Return the element at the specified index. #### Parameters: -| Name | Type | Description | -| :------ | :------ | :------ | -| `index` | *number* | The index to retrieve (0 <= index < size) | +| Name | Type | +| :------ | :------ | +| `index` | *number* | **Returns:** *undefined* \| T -The element at the index, or `undefined` if index is invalid - Implementation of: [List](../interfaces/list.md) -Defined in: [src/list/linkedList.ts:188](https://github.com/havelessbemore/dastal/blob/0f470df/src/list/linkedList.ts#L188) +Defined in: [src/list/linkedList.ts:137](https://github.com/havelessbemore/dastal/blob/dba59a5/src/list/linkedList.ts#L137) ___ @@ -293,18 +263,16 @@ Update the element at the specified index. #### Parameters: -| Name | Type | Description | -| :------ | :------ | :------ | -| `index` | *number* | The index to retrieve (0 <= index < size) | -| `callback` | (`element`: T) => T | A function that receives the previous element and returns the new element. The function is only called if the index is valid | +| Name | Type | +| :------ | :------ | +| `index` | *number* | +| `callback` | (`element`: T) => T | **Returns:** *undefined* \| T -The previous element at the index, or `undefined` if index is invalid - Implementation of: [List](../interfaces/list.md) -Defined in: [src/list/linkedList.ts:203](https://github.com/havelessbemore/dastal/blob/0f470df/src/list/linkedList.ts#L203) +Defined in: [src/list/linkedList.ts:144](https://github.com/havelessbemore/dastal/blob/dba59a5/src/list/linkedList.ts#L144) ___ @@ -312,15 +280,13 @@ ___ ▸ **pop**(): *undefined* \| T -Retrieves and removes the end of the list +Retrieves and removes the end of the list. **Returns:** *undefined* \| T -The value at the end of the list, or `undefined` if empty. - Implementation of: [List](../interfaces/list.md) -Defined in: [src/list/linkedList.ts:217](https://github.com/havelessbemore/dastal/blob/0f470df/src/list/linkedList.ts#L217) +Defined in: [src/list/linkedList.ts:154](https://github.com/havelessbemore/dastal/blob/dba59a5/src/list/linkedList.ts#L154) ___ @@ -338,11 +304,9 @@ Inserts the specified value into the end of the list **Returns:** *number* -`true` upon success, otherwise `false` - Implementation of: [List](../interfaces/list.md) -Defined in: [src/list/linkedList.ts:234](https://github.com/havelessbemore/dastal/blob/0f470df/src/list/linkedList.ts#L234) +Defined in: [src/list/linkedList.ts:165](https://github.com/havelessbemore/dastal/blob/dba59a5/src/list/linkedList.ts#L165) ___ @@ -352,19 +316,20 @@ ___ Retrieves and removes the element at the given index. +A negative index can be used to indicate an offset from the +end of the list. For example, -2 refers to the second to last element of the list. + #### Parameters: -| Name | Type | Description | -| :------ | :------ | :------ | -| `index` | *number* | The index to remove (0 <= index < size) | +| Name | Type | +| :------ | :------ | +| `index` | *number* | **Returns:** *undefined* \| T -The value at the index, or `undefined` if the index is invalid - Implementation of: [List](../interfaces/list.md) -Defined in: [src/list/linkedList.ts:247](https://github.com/havelessbemore/dastal/blob/0f470df/src/list/linkedList.ts#L247) +Defined in: [src/list/linkedList.ts:172](https://github.com/havelessbemore/dastal/blob/dba59a5/src/list/linkedList.ts#L172) ___ @@ -379,18 +344,16 @@ end of the list. For example, -2 refers to the second to last element of the lis #### Parameters: -| Name | Type | Description | -| :------ | :------ | :------ | -| `min?` | *number* | The beginning index of the specified portion of the list, inclusive. Defaults to 0 | -| `max?` | *number* | The end index of the specified portion of the list, exclusive. Defaults to list.size | +| Name | Type | +| :------ | :------ | +| `min?` | *number* | +| `max?` | *number* | **Returns:** [*LinkedList*](linkedlist.md) -a reference to the same list - Implementation of: [List](../interfaces/list.md) -Defined in: [src/list/linkedList.ts:270](https://github.com/havelessbemore/dastal/blob/0f470df/src/list/linkedList.ts#L270) +Defined in: [src/list/linkedList.ts:185](https://github.com/havelessbemore/dastal/blob/dba59a5/src/list/linkedList.ts#L185) ___ @@ -402,18 +365,16 @@ Update the element at the specified index. #### Parameters: -| Name | Type | Description | -| :------ | :------ | :------ | -| `index` | *number* | The index to retrieve (0 <= index < size) | -| `element` | T | The new element to insert at index | +| Name | Type | +| :------ | :------ | +| `index` | *number* | +| `element` | T | **Returns:** *undefined* \| T -The previous element in the index, or undefined if the index is invalid - Implementation of: [List](../interfaces/list.md) -Defined in: [src/list/linkedList.ts:299](https://github.com/havelessbemore/dastal/blob/0f470df/src/list/linkedList.ts#L299) +Defined in: [src/list/linkedList.ts:207](https://github.com/havelessbemore/dastal/blob/dba59a5/src/list/linkedList.ts#L207) ___ @@ -421,15 +382,13 @@ ___ ▸ **shift**(): *undefined* \| T -Retrieves and removes the first element in the list +Retrieves and removes the first element in the list. **Returns:** *undefined* \| T -The value at the front of the list or `undefined` if this list is empty. - Implementation of: [List](../interfaces/list.md) -Defined in: [src/list/linkedList.ts:313](https://github.com/havelessbemore/dastal/blob/0f470df/src/list/linkedList.ts#L313) +Defined in: [src/list/linkedList.ts:217](https://github.com/havelessbemore/dastal/blob/dba59a5/src/list/linkedList.ts#L217) ___ @@ -444,18 +403,36 @@ end of the list. For example, -2 refers to the second to last element of the lis #### Parameters: -| Name | Type | Description | -| :------ | :------ | :------ | -| `min?` | *number* | The beginning index of the specified portion of the list, inclusive. Defaults to 0 | -| `max?` | *number* | The end index of the specified portion of the list, exclusive. Defaults to list.size | +| Name | Type | +| :------ | :------ | +| `min?` | *number* | +| `max?` | *number* | **Returns:** [*LinkedList*](linkedlist.md) -A new list with a copy of the indicated section of the original list +Implementation of: [List](../interfaces/list.md) + +Defined in: [src/list/linkedList.ts:225](https://github.com/havelessbemore/dastal/blob/dba59a5/src/list/linkedList.ts#L225) + +___ + +### sort + +▸ **sort**(`compareFn`: [*CompareFn*](../README.md#comparefn)): [*LinkedList*](linkedlist.md) + +Sorts the elements in place. + +#### Parameters: + +| Name | Type | +| :------ | :------ | +| `compareFn` | [*CompareFn*](../README.md#comparefn) | + +**Returns:** [*LinkedList*](linkedlist.md) Implementation of: [List](../interfaces/list.md) -Defined in: [src/list/linkedList.ts:333](https://github.com/havelessbemore/dastal/blob/0f470df/src/list/linkedList.ts#L333) +Defined in: [src/list/linkedList.ts:256](https://github.com/havelessbemore/dastal/blob/dba59a5/src/list/linkedList.ts#L256) ___ @@ -468,19 +445,17 @@ Returns any deleted elements. #### Parameters: -| Name | Type | Description | -| :------ | :------ | :------ | -| `start?` | *number* | The index from which to start removing elements. Defaults to 0 If > size, start will be set to size. In this case, no element will be deleted but the method can still add elements to the end of the list. If < 0, start will indicate an offset from the end of the list. For example, -2 refers to the second to last element of the list. If < -size, start will be set to 0 | -| `count?` | *number* | The number of elements to remove. Defaults to size - start If >= size - start (that is, if it's >= than the number of elements from start until the end of the list), then all the elements from start until the end of the list will be removed. If <= 0, no elements are removed | -| `elements?` | *Iterable* | The new elements to insert at start. Defaults to none | +| Name | Type | +| :------ | :------ | +| `start?` | *number* | +| `count?` | *number* | +| `elements?` | *Iterable* | **Returns:** [*List*](../interfaces/list.md) -A new list of deleted elements - Implementation of: [List](../interfaces/list.md) -Defined in: [src/list/linkedList.ts:360](https://github.com/havelessbemore/dastal/blob/0f470df/src/list/linkedList.ts#L360) +Defined in: [src/list/linkedList.ts:229](https://github.com/havelessbemore/dastal/blob/dba59a5/src/list/linkedList.ts#L229) ___ @@ -498,11 +473,9 @@ Inserts the specified value into the front of the list **Returns:** *number* -`true` upon success, otherwise `false` - Implementation of: [List](../interfaces/list.md) -Defined in: [src/list/linkedList.ts:405](https://github.com/havelessbemore/dastal/blob/0f470df/src/list/linkedList.ts#L405) +Defined in: [src/list/linkedList.ts:277](https://github.com/havelessbemore/dastal/blob/dba59a5/src/list/linkedList.ts#L277) ___ @@ -514,17 +487,15 @@ Update the elements of the list #### Parameters: -| Name | Type | Description | -| :------ | :------ | :------ | -| `callback` | (`element`: T, `index`: *number*) => T | A function called for each index. Returns the new element | +| Name | Type | +| :------ | :------ | +| `callback` | (`element`: T, `index`: *number*) => T | **Returns:** [*LinkedList*](linkedlist.md) -The list on which this method was called - Implementation of: [List](../interfaces/list.md) -Defined in: [src/list/linkedList.ts:415](https://github.com/havelessbemore/dastal/blob/0f470df/src/list/linkedList.ts#L415) +Defined in: [src/list/linkedList.ts:281](https://github.com/havelessbemore/dastal/blob/dba59a5/src/list/linkedList.ts#L281) ▸ **update**(`min`: *undefined* \| *number*, `callback`: (`element`: T, `index`: *number*) => T): [*LinkedList*](linkedlist.md) @@ -535,18 +506,16 @@ end of the list. For example, -2 refers to the second to last element of the lis #### Parameters: -| Name | Type | Description | -| :------ | :------ | :------ | -| `min` | *undefined* \| *number* | Where to start filling the list, inclusive. Defaults to 0 | -| `callback` | (`element`: T, `index`: *number*) => T | A function called for each index. Returns the new element | +| Name | Type | +| :------ | :------ | +| `min` | *undefined* \| *number* | +| `callback` | (`element`: T, `index`: *number*) => T | **Returns:** [*LinkedList*](linkedlist.md) -The list on which this method was called - Implementation of: [List](../interfaces/list.md) -Defined in: [src/list/linkedList.ts:427](https://github.com/havelessbemore/dastal/blob/0f470df/src/list/linkedList.ts#L427) +Defined in: [src/list/linkedList.ts:282](https://github.com/havelessbemore/dastal/blob/dba59a5/src/list/linkedList.ts#L282) ▸ **update**(`min`: *undefined* \| *number*, `max`: *undefined* \| *number*, `callback`: (`element`: T, `index`: *number*) => T): [*LinkedList*](linkedlist.md) @@ -557,19 +526,17 @@ end of the list. For example, -2 refers to the second to last element of the lis #### Parameters: -| Name | Type | Description | -| :------ | :------ | :------ | -| `min` | *undefined* \| *number* | Where to start filling the list, inclusive. Defaults to 0 | -| `max` | *undefined* \| *number* | Where to stop filling the list, exclusive. Defaults to list.size | -| `callback` | (`element`: T, `index`: *number*) => T | A function called for each index. Returns the new element | +| Name | Type | +| :------ | :------ | +| `min` | *undefined* \| *number* | +| `max` | *undefined* \| *number* | +| `callback` | (`element`: T, `index`: *number*) => T | **Returns:** [*LinkedList*](linkedlist.md) -The list on which this method was called - Implementation of: [List](../interfaces/list.md) -Defined in: [src/list/linkedList.ts:440](https://github.com/havelessbemore/dastal/blob/0f470df/src/list/linkedList.ts#L440) +Defined in: [src/list/linkedList.ts:283](https://github.com/havelessbemore/dastal/blob/dba59a5/src/list/linkedList.ts#L283) ___ @@ -586,15 +553,13 @@ end of the list. For example, -2 refers to the second to last element of the lis #### Parameters: -| Name | Type | Description | -| :------ | :------ | :------ | -| `min?` | *number* | The beginning index of the specified portion of the list, inclusive. Defaults to 0 | -| `max?` | *number* | The end index of the specified portion of the list, exclusive. Defaults to list.size | +| Name | Type | +| :------ | :------ | +| `min?` | *number* | +| `max?` | *number* | **Returns:** *Iterable* -An iterator through the indicated section of the list - Implementation of: [List](../interfaces/list.md) -Defined in: [src/list/linkedList.ts:483](https://github.com/havelessbemore/dastal/blob/0f470df/src/list/linkedList.ts#L483) +Defined in: [src/list/linkedList.ts:314](https://github.com/havelessbemore/dastal/blob/dba59a5/src/list/linkedList.ts#L314) diff --git a/docs/classes/linkedqueue.md b/docs/classes/linkedqueue.md index 6fdb6cc..a999c9d 100644 --- a/docs/classes/linkedqueue.md +++ b/docs/classes/linkedqueue.md @@ -1,4 +1,4 @@ -[dastal - v1.3.1](../README.md) / LinkedQueue +[dastal - v1.4.0](../README.md) / LinkedQueue # Class: LinkedQueue @@ -38,6 +38,8 @@ A linked list implementation of the [Queue](../interfaces/queue.md) interface \+ **new LinkedQueue**(`elements?`: *Iterable*): [*LinkedQueue*](linkedqueue.md) +Instantiate the queue. + #### Type parameters: | Name | @@ -46,13 +48,13 @@ A linked list implementation of the [Queue](../interfaces/queue.md) interface #### Parameters: -| Name | Type | -| :------ | :------ | -| `elements?` | *Iterable* | +| Name | Type | Description | +| :------ | :------ | :------ | +| `elements?` | *Iterable* | A set of elements to initialize the queue with. | **Returns:** [*LinkedQueue*](linkedqueue.md) -Defined in: [src/queue/linkedQueue.ts:11](https://github.com/havelessbemore/dastal/blob/0f470df/src/queue/linkedQueue.ts#L11) +Defined in: [src/queue/linkedQueue.ts:11](https://github.com/havelessbemore/dastal/blob/dba59a5/src/queue/linkedQueue.ts#L11) ## Accessors @@ -66,7 +68,7 @@ The number of elements in this queue Implementation of: [Queue](../interfaces/queue.md).[size](../interfaces/queue.md#size) -Defined in: [src/queue/linkedQueue.ts:49](https://github.com/havelessbemore/dastal/blob/0f470df/src/queue/linkedQueue.ts#L49) +Defined in: [src/queue/linkedQueue.ts:37](https://github.com/havelessbemore/dastal/blob/dba59a5/src/queue/linkedQueue.ts#L37) ## Methods @@ -84,7 +86,7 @@ An iterator through the queue Implementation of: [Queue](../interfaces/queue.md) -Defined in: [src/queue/linkedQueue.ts:59](https://github.com/havelessbemore/dastal/blob/0f470df/src/queue/linkedQueue.ts#L59) +Defined in: [src/queue/linkedQueue.ts:47](https://github.com/havelessbemore/dastal/blob/dba59a5/src/queue/linkedQueue.ts#L47) ___ @@ -98,7 +100,7 @@ Removes all elements from this queue Implementation of: [Queue](../interfaces/queue.md) -Defined in: [src/queue/linkedQueue.ts:19](https://github.com/havelessbemore/dastal/blob/0f470df/src/queue/linkedQueue.ts#L19) +Defined in: [src/queue/linkedQueue.ts:21](https://github.com/havelessbemore/dastal/blob/dba59a5/src/queue/linkedQueue.ts#L21) ___ @@ -110,11 +112,9 @@ Retrieves and removes the head of this queue **Returns:** *undefined* \| T -The element at the head of the queue or `undefined` if this queue is empty. - Implementation of: [Queue](../interfaces/queue.md) -Defined in: [src/queue/linkedQueue.ts:27](https://github.com/havelessbemore/dastal/blob/0f470df/src/queue/linkedQueue.ts#L27) +Defined in: [src/queue/linkedQueue.ts:25](https://github.com/havelessbemore/dastal/blob/dba59a5/src/queue/linkedQueue.ts#L25) ___ @@ -122,19 +122,19 @@ ___ ▸ **enqueue**(`element`: T): *number* -Inserts the specified element into this queue +Inserts the specified value into this queue #### Parameters: -| Name | Type | Description | -| :------ | :------ | :------ | -| `element` | T | The element to be inserted | +| Name | Type | +| :------ | :------ | +| `element` | T | **Returns:** *number* Implementation of: [Queue](../interfaces/queue.md) -Defined in: [src/queue/linkedQueue.ts:35](https://github.com/havelessbemore/dastal/blob/0f470df/src/queue/linkedQueue.ts#L35) +Defined in: [src/queue/linkedQueue.ts:29](https://github.com/havelessbemore/dastal/blob/dba59a5/src/queue/linkedQueue.ts#L29) ___ @@ -146,8 +146,6 @@ Retrieves, but does not remove, the head of this queue **Returns:** *undefined* \| T -The element at the head of the queue or `undefined` if this queue is empty. - Implementation of: [Queue](../interfaces/queue.md) -Defined in: [src/queue/linkedQueue.ts:43](https://github.com/havelessbemore/dastal/blob/0f470df/src/queue/linkedQueue.ts#L43) +Defined in: [src/queue/linkedQueue.ts:33](https://github.com/havelessbemore/dastal/blob/dba59a5/src/queue/linkedQueue.ts#L33) diff --git a/docs/classes/linkedstack.md b/docs/classes/linkedstack.md index 1978b85..48376db 100644 --- a/docs/classes/linkedstack.md +++ b/docs/classes/linkedstack.md @@ -1,4 +1,4 @@ -[dastal - v1.3.1](../README.md) / LinkedStack +[dastal - v1.4.0](../README.md) / LinkedStack # Class: LinkedStack @@ -38,6 +38,8 @@ A linked list implementation of the [Stack](../interfaces/stack.md) interface \+ **new LinkedStack**(`elements?`: *Iterable*): [*LinkedStack*](linkedstack.md) +Instantiate the stack. + #### Type parameters: | Name | @@ -46,13 +48,13 @@ A linked list implementation of the [Stack](../interfaces/stack.md) interface #### Parameters: -| Name | Type | -| :------ | :------ | -| `elements?` | *Iterable* | +| Name | Type | Description | +| :------ | :------ | :------ | +| `elements?` | *Iterable* | A set of elements to initialize the stack with. | **Returns:** [*LinkedStack*](linkedstack.md) -Defined in: [src/stack/linkedStack.ts:11](https://github.com/havelessbemore/dastal/blob/0f470df/src/stack/linkedStack.ts#L11) +Defined in: [src/stack/linkedStack.ts:11](https://github.com/havelessbemore/dastal/blob/dba59a5/src/stack/linkedStack.ts#L11) ## Accessors @@ -66,7 +68,7 @@ The number of elements in the stack Implementation of: [Stack](../interfaces/stack.md).[size](../interfaces/stack.md#size) -Defined in: [src/stack/linkedStack.ts:54](https://github.com/havelessbemore/dastal/blob/0f470df/src/stack/linkedStack.ts#L54) +Defined in: [src/stack/linkedStack.ts:40](https://github.com/havelessbemore/dastal/blob/dba59a5/src/stack/linkedStack.ts#L40) ## Methods @@ -84,7 +86,7 @@ An iterator through the stack Implementation of: [Stack](../interfaces/stack.md) -Defined in: [src/stack/linkedStack.ts:64](https://github.com/havelessbemore/dastal/blob/0f470df/src/stack/linkedStack.ts#L64) +Defined in: [src/stack/linkedStack.ts:50](https://github.com/havelessbemore/dastal/blob/dba59a5/src/stack/linkedStack.ts#L50) ___ @@ -98,7 +100,7 @@ Removes all elements from the stack Implementation of: [Stack](../interfaces/stack.md) -Defined in: [src/stack/linkedStack.ts:22](https://github.com/havelessbemore/dastal/blob/0f470df/src/stack/linkedStack.ts#L22) +Defined in: [src/stack/linkedStack.ts:24](https://github.com/havelessbemore/dastal/blob/dba59a5/src/stack/linkedStack.ts#L24) ___ @@ -110,11 +112,9 @@ Retrieves, but does not remove, the top of the stack **Returns:** *undefined* \| T -The element at the top of the stack or `undefined` if empty. - Implementation of: [Stack](../interfaces/stack.md) -Defined in: [src/stack/linkedStack.ts:30](https://github.com/havelessbemore/dastal/blob/0f470df/src/stack/linkedStack.ts#L30) +Defined in: [src/stack/linkedStack.ts:28](https://github.com/havelessbemore/dastal/blob/dba59a5/src/stack/linkedStack.ts#L28) ___ @@ -126,11 +126,9 @@ Retrieves and removes the top of the stack **Returns:** *undefined* \| T -The element at the top of the stack or `undefined` if empty. - Implementation of: [Stack](../interfaces/stack.md) -Defined in: [src/stack/linkedStack.ts:38](https://github.com/havelessbemore/dastal/blob/0f470df/src/stack/linkedStack.ts#L38) +Defined in: [src/stack/linkedStack.ts:32](https://github.com/havelessbemore/dastal/blob/dba59a5/src/stack/linkedStack.ts#L32) ___ @@ -138,18 +136,16 @@ ___ ▸ **push**(`element`: T): *number* -Inserts a element into the stack +Inserts an element into the stack #### Parameters: -| Name | Type | Description | -| :------ | :------ | :------ | -| `element` | T | The element to be inserted | +| Name | Type | +| :------ | :------ | +| `element` | T | **Returns:** *number* -The new size of the stack - Implementation of: [Stack](../interfaces/stack.md) -Defined in: [src/stack/linkedStack.ts:48](https://github.com/havelessbemore/dastal/blob/0f470df/src/stack/linkedStack.ts#L48) +Defined in: [src/stack/linkedStack.ts:36](https://github.com/havelessbemore/dastal/blob/dba59a5/src/stack/linkedStack.ts#L36) diff --git a/docs/classes/skewheap.md b/docs/classes/skewheap.md new file mode 100644 index 0000000..980f3f9 --- /dev/null +++ b/docs/classes/skewheap.md @@ -0,0 +1,351 @@ +[dastal - v1.4.0](../README.md) / SkewHeap + +# Class: SkewHeap + +## Type parameters + +| Name | +| :------ | +| `T` | + +## Implements + +* [*Heap*](../interfaces/heap.md) + +## Table of contents + +### Constructors + +- [constructor](skewheap.md#constructor) + +### Accessors + +- [size](skewheap.md#size) + +### Methods + +- [[Symbol.iterator]](skewheap.md#[symbol.iterator]) +- [addAll](skewheap.md#addall) +- [clear](skewheap.md#clear) +- [comparator](skewheap.md#comparator) +- [contains](skewheap.md#contains) +- [delete](skewheap.md#delete) +- [dump](skewheap.md#dump) +- [merge](skewheap.md#merge) +- [peek](skewheap.md#peek) +- [pop](skewheap.md#pop) +- [push](skewheap.md#push) +- [pushPop](skewheap.md#pushpop) +- [replace](skewheap.md#replace) +- [update](skewheap.md#update) + +## Constructors + +### constructor + +\+ **new SkewHeap**(`compareFn`: [*CompareFn*](../README.md#comparefn), `elements?`: *Iterable*): [*SkewHeap*](skewheap.md) + +Instantiate a heap. + +#### Type parameters: + +| Name | +| :------ | +| `T` | + +#### Parameters: + +| Name | Type | Description | +| :------ | :------ | :------ | +| `compareFn` | [*CompareFn*](../README.md#comparefn) | The function to determine the order of elements. | +| `elements?` | *Iterable* | A set of elements to initialize the list with. | + +**Returns:** [*SkewHeap*](skewheap.md) + +Defined in: src/heap/skewHeap.ts:23 + +## Accessors + +### size + +• get **size**(): *number* + +The number of elements in the heap. + +**Returns:** *number* + +Implementation of: [Heap](../interfaces/heap.md).[size](../interfaces/heap.md#size) + +Defined in: src/heap/skewHeap.ts:140 + +## Methods + +### [Symbol.iterator] + +▸ **[Symbol.iterator]**(): *Iterator* + +Iterate through the heap in sorted order. + +**Note:** Unexpected behavior can occur if the collection is modified during iteration. + +**Returns:** *Iterator* + +An iterator through the heap. + +Implementation of: [Heap](../interfaces/heap.md) + +Defined in: src/heap/skewHeap.ts:150 + +___ + +### addAll + +▸ **addAll**(`elements`: *Iterable*): *number* + +Insert a set of elements into the heap. + +#### Parameters: + +| Name | Type | +| :------ | :------ | +| `elements` | *Iterable* | + +**Returns:** *number* + +The new size of the list. + +Implementation of: [Heap](../interfaces/heap.md) + +Defined in: src/heap/skewHeap.ts:36 + +___ + +### clear + +▸ **clear**(): *void* + +Remove all elements. + +**Returns:** *void* + +Implementation of: [Heap](../interfaces/heap.md) + +Defined in: src/heap/skewHeap.ts:43 + +___ + +### comparator + +▸ **comparator**(): [*CompareFn*](../README.md#comparefn) + +**Returns:** [*CompareFn*](../README.md#comparefn) + +The function with which elements are sorted + +Implementation of: [Heap](../interfaces/heap.md) + +Defined in: src/heap/skewHeap.ts:48 + +___ + +### contains + +▸ **contains**(`element`: T): *boolean* + +Check if an element is in the heap. + +#### Parameters: + +| Name | Type | +| :------ | :------ | +| `element` | T | + +**Returns:** *boolean* + +`true` if the element was found, otherwise `false`. + +Implementation of: [Heap](../interfaces/heap.md) + +Defined in: src/heap/skewHeap.ts:52 + +___ + +### delete + +▸ **delete**(`element`: T): *boolean* + +Delete an element from the heap. + +#### Parameters: + +| Name | Type | +| :------ | :------ | +| `element` | T | + +**Returns:** *boolean* + +`true` if the element was found and deleted, otherwise `false`. + +Implementation of: [Heap](../interfaces/heap.md) + +Defined in: src/heap/skewHeap.ts:61 + +___ + +### dump + +▸ **dump**(): *Iterable* + +Iterate through the heap. + +**Note:** Unexpected behavior can occur if the collection is modified during iteration. + +**Returns:** *Iterable* + +Implementation of: [Heap](../interfaces/heap.md) + +Defined in: src/heap/skewHeap.ts:86 + +___ + +### merge + +▸ **merge**(`heap`: [*Heap*](../interfaces/heap.md)): [*SkewHeap*](skewheap.md) + +Join with a different heap and modify the existing heap to +contain elements of both. Does not modify the input. + +#### Parameters: + +| Name | Type | +| :------ | :------ | +| `heap` | [*Heap*](../interfaces/heap.md) | + +**Returns:** [*SkewHeap*](skewheap.md) + +The new heap size. + +Implementation of: [Heap](../interfaces/heap.md) + +Defined in: src/heap/skewHeap.ts:92 + +___ + +### peek + +▸ **peek**(): *undefined* \| T + +Retrieves, but does not remove, the top of the heap. + +**Returns:** *undefined* \| T + +The element at the top of the heap or `undefined` if empty. + +Implementation of: [Heap](../interfaces/heap.md) + +Defined in: src/heap/skewHeap.ts:105 + +___ + +### pop + +▸ **pop**(): *undefined* \| T + +Remove the top of the heap (AKA extract). + +**Returns:** *undefined* \| T + +The element at the top of the heap or `undefined` if empty. + +Implementation of: [Heap](../interfaces/heap.md) + +Defined in: src/heap/skewHeap.ts:109 + +___ + +### push + +▸ **push**(`value`: T): *number* + +Inserts an element into the heap (AKA insert, add). + +#### Parameters: + +| Name | Type | +| :------ | :------ | +| `value` | T | + +**Returns:** *number* + +The new size of the heap. + +Implementation of: [Heap](../interfaces/heap.md) + +Defined in: src/heap/skewHeap.ts:119 + +___ + +### pushPop + +▸ **pushPop**(`value`: T): T + +Insert an element and then remove the top of the heap. + +#### Parameters: + +| Name | Type | +| :------ | :------ | +| `value` | T | + +**Returns:** T + +The element at the top of the heap. + +Implementation of: [Heap](../interfaces/heap.md) + +Defined in: src/heap/skewHeap.ts:124 + +___ + +### replace + +▸ **replace**(`value`: T): *undefined* \| T + +Remove the top of the heap and then insert a new element (AKA popPush). + +#### Parameters: + +| Name | Type | +| :------ | :------ | +| `value` | T | + +**Returns:** *undefined* \| T + +The element at the top of the heap or `undefined` if empty. + +Implementation of: [Heap](../interfaces/heap.md) + +Defined in: src/heap/skewHeap.ts:129 + +___ + +### update + +▸ **update**(`curElement`: T, `newElement`: T): *boolean* + +Update a specific element. + +#### Parameters: + +| Name | Type | +| :------ | :------ | +| `curElement` | T | +| `newElement` | T | + +**Returns:** *boolean* + +`true` if curElement was found and updated, otherwise `false`. + +Implementation of: [Heap](../interfaces/heap.md) + +Defined in: src/heap/skewHeap.ts:165 diff --git a/docs/interfaces/doublylinkednode.md b/docs/interfaces/doublylinkednode.md index 218d8de..ea23a95 100644 --- a/docs/interfaces/doublylinkednode.md +++ b/docs/interfaces/doublylinkednode.md @@ -1,4 +1,4 @@ -[dastal - v1.3.1](../README.md) / DoublyLinkedNode +[dastal - v1.4.0](../README.md) / DoublyLinkedNode # Interface: DoublyLinkedNode @@ -28,7 +28,7 @@ Each node links to its neighbors on the left (prev) and right (next) of it. A link to the node's next (right) neighbor -Defined in: [src/list/doublyLinkedList.ts:13](https://github.com/havelessbemore/dastal/blob/0f470df/src/list/doublyLinkedList.ts#L13) +Defined in: [src/list/doublyLinkedList.ts:14](https://github.com/havelessbemore/dastal/blob/dba59a5/src/list/doublyLinkedList.ts#L14) ___ @@ -38,7 +38,7 @@ ___ A link to the node's previous (left) neighbor -Defined in: [src/list/doublyLinkedList.ts:17](https://github.com/havelessbemore/dastal/blob/0f470df/src/list/doublyLinkedList.ts#L17) +Defined in: [src/list/doublyLinkedList.ts:18](https://github.com/havelessbemore/dastal/blob/dba59a5/src/list/doublyLinkedList.ts#L18) ___ @@ -48,4 +48,4 @@ ___ The value of the node -Defined in: [src/list/doublyLinkedList.ts:21](https://github.com/havelessbemore/dastal/blob/0f470df/src/list/doublyLinkedList.ts#L21) +Defined in: [src/list/doublyLinkedList.ts:22](https://github.com/havelessbemore/dastal/blob/dba59a5/src/list/doublyLinkedList.ts#L22) diff --git a/docs/interfaces/heap.md b/docs/interfaces/heap.md new file mode 100644 index 0000000..c8311e3 --- /dev/null +++ b/docs/interfaces/heap.md @@ -0,0 +1,337 @@ +[dastal - v1.4.0](../README.md) / Heap + +# Interface: Heap + +A specialized tree-based data structure that satisfies the heap property. + +**Heap property**: For any given node N, the key (e.g. value) of N is greater than or equal to the key of its children. + +In a heap, the highest priority element (relative to its ordering) is always stored at the root. +However, a heap is not a sorted structure; it can be regarded as being partially ordered. +The heap property only applies between a parent node and its descendants. There is no +implied ordering between siblings or cousins and no implied sequence for an ordered traversal. + +A heap is a useful data structure when it is necessary to repeatedly +remove the object with the highest priority. In the sense, it can be used to implement +a priority queue. + +#### Iterate +- Iterate the heap: [dump](heap.md#dump) +- Iterate the heap in sorted order: {@link [Symbol.iterator]} + +#### Get +- Get the size of the heap: [size](heap.md#size) +- Get the top element: [peek](heap.md#peek) +- Check if the heap contains a given element: [contains](heap.md#contains) +- Get the heap's sorting method: [comparator](heap.md#comparator) + +#### Set +- Update an element: [update](heap.md#update) + +#### Add +- Add 1 element: [push](heap.md#push) +- Add 1 heap: [merge](heap.md#merge) +- Add multiple elements: [addAll](heap.md#addall) + +#### Remove +- Remove the top element: [pop](heap.md#pop) +- Delete a given element: [delete](heap.md#delete) +- Remove all elements: [clear](heap.md#clear) + +#### Add and Remove +- Add and then remove the top element: [pushPop](heap.md#pushpop) +- Remove the top element and then add an element: [replace](heap.md#replace) + +## Type parameters + +| Name | +| :------ | +| `T` | + +## Hierarchy + +* *Iterable* + +* [*Sorted*](sorted.md) + + ↳ **Heap** + +## Implemented by + +* [*BinaryHeap*](../classes/binaryheap.md) +* [*SkewHeap*](../classes/skewheap.md) + +## Table of contents + +### Properties + +- [size](heap.md#size) + +### Methods + +- [[Symbol.iterator]](heap.md#[symbol.iterator]) +- [addAll](heap.md#addall) +- [clear](heap.md#clear) +- [comparator](heap.md#comparator) +- [contains](heap.md#contains) +- [delete](heap.md#delete) +- [dump](heap.md#dump) +- [merge](heap.md#merge) +- [peek](heap.md#peek) +- [pop](heap.md#pop) +- [push](heap.md#push) +- [pushPop](heap.md#pushpop) +- [replace](heap.md#replace) +- [update](heap.md#update) + +## Properties + +### size + +• `Readonly` **size**: *number* + +The number of elements in the heap. + +Defined in: [src/heap/heap.ts:127](https://github.com/havelessbemore/dastal/blob/dba59a5/src/heap/heap.ts#L127) + +## Methods + +### [Symbol.iterator] + +▸ **[Symbol.iterator]**(): *Iterator* + +**Returns:** *Iterator* + +Inherited from: Iterable.\_\_@iterator + +Defined in: node_modules/typescript/lib/lib.es2015.iterable.d.ts:51 + +___ + +### addAll + +▸ **addAll**(`elements`: *Iterable*): *number* + +Insert a set of elements into the heap. + +#### Parameters: + +| Name | Type | Description | +| :------ | :------ | :------ | +| `elements` | *Iterable* | The elements to insert. | + +**Returns:** *number* + +The new size of the list. + +Defined in: [src/heap/heap.ts:52](https://github.com/havelessbemore/dastal/blob/dba59a5/src/heap/heap.ts#L52) + +___ + +### clear + +▸ **clear**(): *void* + +Remove all elements. + +**Returns:** *void* + +Defined in: [src/heap/heap.ts:56](https://github.com/havelessbemore/dastal/blob/dba59a5/src/heap/heap.ts#L56) + +___ + +### comparator + +▸ **comparator**(): [*CompareFn*](../README.md#comparefn) + +**Returns:** [*CompareFn*](../README.md#comparefn) + +The function with which elements are sorted + +Inherited from: [Sorted](sorted.md) + +Defined in: [src/index.ts:47](https://github.com/havelessbemore/dastal/blob/dba59a5/src/index.ts#L47) + +___ + +### contains + +▸ **contains**(`element`: T): *boolean* + +Check if an element is in the heap. + +#### Parameters: + +| Name | Type | Description | +| :------ | :------ | :------ | +| `element` | T | The element to find. | + +**Returns:** *boolean* + +`true` if the element was found, otherwise `false`. + +Defined in: [src/heap/heap.ts:64](https://github.com/havelessbemore/dastal/blob/dba59a5/src/heap/heap.ts#L64) + +___ + +### delete + +▸ **delete**(`element`: T): *boolean* + +Delete an element from the heap. + +#### Parameters: + +| Name | Type | Description | +| :------ | :------ | :------ | +| `element` | T | The element to delete. | + +**Returns:** *boolean* + +`true` if the element was found and deleted, otherwise `false`. + +Defined in: [src/heap/heap.ts:72](https://github.com/havelessbemore/dastal/blob/dba59a5/src/heap/heap.ts#L72) + +___ + +### dump + +▸ **dump**(): *Iterable* + +Iterate through the heap. + +**Note:** Unexpected behavior can occur if the collection is modified during iteration. + +**Returns:** *Iterable* + +Defined in: [src/heap/heap.ts:78](https://github.com/havelessbemore/dastal/blob/dba59a5/src/heap/heap.ts#L78) + +___ + +### merge + +▸ **merge**(`heap`: [*Heap*](heap.md)): [*Heap*](heap.md) + +Join with a different heap and modify the existing heap to +contain elements of both. Does not modify the input. + +#### Parameters: + +| Name | Type | Description | +| :------ | :------ | :------ | +| `heap` | [*Heap*](heap.md) | The heap to join with. | + +**Returns:** [*Heap*](heap.md) + +The new heap size. + +Defined in: [src/heap/heap.ts:87](https://github.com/havelessbemore/dastal/blob/dba59a5/src/heap/heap.ts#L87) + +___ + +### peek + +▸ **peek**(): *undefined* \| T + +Retrieves, but does not remove, the top of the heap. + +**Returns:** *undefined* \| T + +The element at the top of the heap or `undefined` if empty. + +Defined in: [src/heap/heap.ts:93](https://github.com/havelessbemore/dastal/blob/dba59a5/src/heap/heap.ts#L93) + +___ + +### pop + +▸ **pop**(): *undefined* \| T + +Remove the top of the heap (AKA extract). + +**Returns:** *undefined* \| T + +The element at the top of the heap or `undefined` if empty. + +Defined in: [src/heap/heap.ts:99](https://github.com/havelessbemore/dastal/blob/dba59a5/src/heap/heap.ts#L99) + +___ + +### push + +▸ **push**(`element`: T): *number* + +Inserts an element into the heap (AKA insert, add). + +#### Parameters: + +| Name | Type | Description | +| :------ | :------ | :------ | +| `element` | T | The element to be inserted. | + +**Returns:** *number* + +The new size of the heap. + +Defined in: [src/heap/heap.ts:107](https://github.com/havelessbemore/dastal/blob/dba59a5/src/heap/heap.ts#L107) + +___ + +### pushPop + +▸ **pushPop**(`element`: T): T + +Insert an element and then remove the top of the heap. + +#### Parameters: + +| Name | Type | Description | +| :------ | :------ | :------ | +| `element` | T | The element to be inserted. | + +**Returns:** T + +The element at the top of the heap. + +Defined in: [src/heap/heap.ts:115](https://github.com/havelessbemore/dastal/blob/dba59a5/src/heap/heap.ts#L115) + +___ + +### replace + +▸ **replace**(`element`: T): *undefined* \| T + +Remove the top of the heap and then insert a new element (AKA popPush). + +#### Parameters: + +| Name | Type | Description | +| :------ | :------ | :------ | +| `element` | T | The element to be inserted. | + +**Returns:** *undefined* \| T + +The element at the top of the heap or `undefined` if empty. + +Defined in: [src/heap/heap.ts:123](https://github.com/havelessbemore/dastal/blob/dba59a5/src/heap/heap.ts#L123) + +___ + +### update + +▸ **update**(`curElement`: T, `newElement`: T): *boolean* + +Update a specific element. + +#### Parameters: + +| Name | Type | Description | +| :------ | :------ | :------ | +| `curElement` | T | The element to update. | +| `newElement` | T | The new element to insert. | + +**Returns:** *boolean* + +`true` if curElement was found and updated, otherwise `false`. + +Defined in: [src/heap/heap.ts:136](https://github.com/havelessbemore/dastal/blob/dba59a5/src/heap/heap.ts#L136) diff --git a/docs/interfaces/linkednode.md b/docs/interfaces/linkednode.md index 91621a4..3f52d06 100644 --- a/docs/interfaces/linkednode.md +++ b/docs/interfaces/linkednode.md @@ -1,4 +1,4 @@ -[dastal - v1.3.1](../README.md) / LinkedNode +[dastal - v1.4.0](../README.md) / LinkedNode # Interface: LinkedNode @@ -27,7 +27,7 @@ Each node links to its next neighbor. A link to the node's neighbor -Defined in: [src/list/linkedList.ts:13](https://github.com/havelessbemore/dastal/blob/0f470df/src/list/linkedList.ts#L13) +Defined in: [src/list/linkedList.ts:14](https://github.com/havelessbemore/dastal/blob/dba59a5/src/list/linkedList.ts#L14) ___ @@ -37,4 +37,4 @@ ___ The value of the node -Defined in: [src/list/linkedList.ts:17](https://github.com/havelessbemore/dastal/blob/0f470df/src/list/linkedList.ts#L17) +Defined in: [src/list/linkedList.ts:18](https://github.com/havelessbemore/dastal/blob/dba59a5/src/list/linkedList.ts#L18) diff --git a/docs/interfaces/list.md b/docs/interfaces/list.md index f0d4fb4..da5d071 100644 --- a/docs/interfaces/list.md +++ b/docs/interfaces/list.md @@ -1,4 +1,4 @@ -[dastal - v1.3.1](../README.md) / List +[dastal - v1.4.0](../README.md) / List # Interface: List @@ -10,6 +10,7 @@ where an element is inserted. Elements can be accessed by their integer index (p - Iterate a subset of the list: [view](list.md#view) #### Get +- Get the size of the list: [size](list.md#size) - Get the element at a given index: [get](list.md#get) - Get the elements in a given range: [slice](list.md#slice) @@ -18,6 +19,7 @@ where an element is inserted. Elements can be accessed by their integer index (p - Add 1 at the end: [push](list.md#push) - Add 1 at a given index: [add](list.md#add) - Add 1+ at a given index: [addAll](list.md#addall) +- Add 1+ into a new list: [concat](list.md#concat) #### Set - Set 1 index: [set](list.md#set) @@ -25,12 +27,15 @@ where an element is inserted. Elements can be accessed by their integer index (p - Set a range to 1 element: [fill](list.md#fill) - Set a range to a copy of another range within the list: [copyWithin](list.md#copywithin) - Set a range: [update](list.md#update) +- Sort the list: [sort](list.md#sort) +- Reverse the list [reverse](list.md#reverse) #### Remove - Remove 1 from the start: [shift](list.md#shift) - Remove 1 from the end: [pop](list.md#pop) - Remove 1 from a given index: [remove](list.md#remove) - Remove a range (and add new elements): [splice](list.md#splice) +- Remove all elements: [clear](list.md#clear) ## Type parameters @@ -42,6 +47,8 @@ where an element is inserted. Elements can be accessed by their integer index (p * *Iterable* +* [*Sortable*](sortable.md) + ↳ **List** ## Implemented by @@ -74,6 +81,7 @@ where an element is inserted. Elements can be accessed by their integer index (p - [set](list.md#set) - [shift](list.md#shift) - [slice](list.md#slice) +- [sort](list.md#sort) - [splice](list.md#splice) - [unshift](list.md#unshift) - [update](list.md#update) @@ -87,7 +95,7 @@ where an element is inserted. Elements can be accessed by their integer index (p The number of elements in this list -Defined in: [src/list/list.ts:167](https://github.com/havelessbemore/dastal/blob/0f470df/src/list/list.ts#L167) +Defined in: [src/list/list.ts:174](https://github.com/havelessbemore/dastal/blob/dba59a5/src/list/list.ts#L174) ## Methods @@ -120,7 +128,7 @@ Add the element at the specified index. The new size of the list -Defined in: [src/list/list.ts:41](https://github.com/havelessbemore/dastal/blob/0f470df/src/list/list.ts#L41) +Defined in: [src/list/list.ts:48](https://github.com/havelessbemore/dastal/blob/dba59a5/src/list/list.ts#L48) ___ @@ -141,7 +149,7 @@ Add elements at the specified index. The new size of the list -Defined in: [src/list/list.ts:50](https://github.com/havelessbemore/dastal/blob/0f470df/src/list/list.ts#L50) +Defined in: [src/list/list.ts:57](https://github.com/havelessbemore/dastal/blob/dba59a5/src/list/list.ts#L57) ___ @@ -153,7 +161,7 @@ Removes all elements **Returns:** *void* -Defined in: [src/list/list.ts:54](https://github.com/havelessbemore/dastal/blob/0f470df/src/list/list.ts#L54) +Defined in: [src/list/list.ts:61](https://github.com/havelessbemore/dastal/blob/dba59a5/src/list/list.ts#L61) ___ @@ -175,7 +183,7 @@ A new list consisting of the elements in the list on which it is called, followed in order by the elements of each argument (if the argument is an iterable) or the argument itself. It does not recurse into nested iterable arguments -Defined in: [src/list/list.ts:64](https://github.com/havelessbemore/dastal/blob/0f470df/src/list/list.ts#L64) +Defined in: [src/list/list.ts:71](https://github.com/havelessbemore/dastal/blob/dba59a5/src/list/list.ts#L71) ___ @@ -203,7 +211,7 @@ the copied sequence will be trimmed to fit list.size The list -Defined in: [src/list/list.ts:80](https://github.com/havelessbemore/dastal/blob/0f470df/src/list/list.ts#L80) +Defined in: [src/list/list.ts:87](https://github.com/havelessbemore/dastal/blob/dba59a5/src/list/list.ts#L87) ___ @@ -228,7 +236,7 @@ end of the list. For example, -2 refers to the second to last element of the lis The list on which this method was called -Defined in: [src/list/list.ts:93](https://github.com/havelessbemore/dastal/blob/0f470df/src/list/list.ts#L93) +Defined in: [src/list/list.ts:100](https://github.com/havelessbemore/dastal/blob/dba59a5/src/list/list.ts#L100) ___ @@ -248,7 +256,7 @@ Return the element at the specified index. The element at the index, or `undefined` if index is invalid -Defined in: [src/list/list.ts:101](https://github.com/havelessbemore/dastal/blob/0f470df/src/list/list.ts#L101) +Defined in: [src/list/list.ts:108](https://github.com/havelessbemore/dastal/blob/dba59a5/src/list/list.ts#L108) ___ @@ -269,7 +277,7 @@ Update the element at the specified index. The previous element at the index, or `undefined` if index is invalid -Defined in: [src/list/list.ts:111](https://github.com/havelessbemore/dastal/blob/0f470df/src/list/list.ts#L111) +Defined in: [src/list/list.ts:118](https://github.com/havelessbemore/dastal/blob/dba59a5/src/list/list.ts#L118) ___ @@ -283,7 +291,7 @@ Retrieves and removes the end of the list. The value at the end of the list, or `undefined` if empty. -Defined in: [src/list/list.ts:117](https://github.com/havelessbemore/dastal/blob/0f470df/src/list/list.ts#L117) +Defined in: [src/list/list.ts:124](https://github.com/havelessbemore/dastal/blob/dba59a5/src/list/list.ts#L124) ___ @@ -303,7 +311,7 @@ Inserts the specified value into the end of the list The new size of the list -Defined in: [src/list/list.ts:125](https://github.com/havelessbemore/dastal/blob/0f470df/src/list/list.ts#L125) +Defined in: [src/list/list.ts:132](https://github.com/havelessbemore/dastal/blob/dba59a5/src/list/list.ts#L132) ___ @@ -326,7 +334,7 @@ end of the list. For example, -2 refers to the second to last element of the lis The value at the index, or `undefined` if the index is invalid -Defined in: [src/list/list.ts:136](https://github.com/havelessbemore/dastal/blob/0f470df/src/list/list.ts#L136) +Defined in: [src/list/list.ts:143](https://github.com/havelessbemore/dastal/blob/dba59a5/src/list/list.ts#L143) ___ @@ -350,7 +358,7 @@ end of the list. For example, -2 refers to the second to last element of the lis a reference to the same list -Defined in: [src/list/list.ts:148](https://github.com/havelessbemore/dastal/blob/0f470df/src/list/list.ts#L148) +Defined in: [src/list/list.ts:155](https://github.com/havelessbemore/dastal/blob/dba59a5/src/list/list.ts#L155) ___ @@ -371,7 +379,7 @@ Update the element at the specified index. The previous element in the index, or undefined if the index is invalid -Defined in: [src/list/list.ts:157](https://github.com/havelessbemore/dastal/blob/0f470df/src/list/list.ts#L157) +Defined in: [src/list/list.ts:164](https://github.com/havelessbemore/dastal/blob/dba59a5/src/list/list.ts#L164) ___ @@ -385,7 +393,7 @@ Retrieves and removes the first element in the list. The value at the front of the list or `undefined` if this list is empty. -Defined in: [src/list/list.ts:163](https://github.com/havelessbemore/dastal/blob/0f470df/src/list/list.ts#L163) +Defined in: [src/list/list.ts:170](https://github.com/havelessbemore/dastal/blob/dba59a5/src/list/list.ts#L170) ___ @@ -409,7 +417,29 @@ end of the list. For example, -2 refers to the second to last element of the lis A new list with a copy of the indicated section of the original list -Defined in: [src/list/list.ts:179](https://github.com/havelessbemore/dastal/blob/0f470df/src/list/list.ts#L179) +Defined in: [src/list/list.ts:186](https://github.com/havelessbemore/dastal/blob/dba59a5/src/list/list.ts#L186) + +___ + +### sort + +▸ **sort**(`compareFn`: [*CompareFn*](../README.md#comparefn)): [*List*](list.md) + +Sorts the elements in place. + +#### Parameters: + +| Name | Type | Description | +| :------ | :------ | :------ | +| `compareFn` | [*CompareFn*](../README.md#comparefn) | A function used to determine the order of elements. It is expected to return: - A negative value if first argument < second argument - Zero if first argument == second argument - A positive value if first argument > second argument | + +**Returns:** [*List*](list.md) + +The object this method was called on + +Inherited from: [Sortable](sortable.md) + +Defined in: [src/index.ts:38](https://github.com/havelessbemore/dastal/blob/dba59a5/src/index.ts#L38) ___ @@ -432,7 +462,7 @@ Returns any deleted elements. A new list of deleted elements -Defined in: [src/list/list.ts:204](https://github.com/havelessbemore/dastal/blob/0f470df/src/list/list.ts#L204) +Defined in: [src/list/list.ts:211](https://github.com/havelessbemore/dastal/blob/dba59a5/src/list/list.ts#L211) ___ @@ -452,7 +482,7 @@ Inserts the specified value into the front of the list The new size of the list -Defined in: [src/list/list.ts:212](https://github.com/havelessbemore/dastal/blob/0f470df/src/list/list.ts#L212) +Defined in: [src/list/list.ts:219](https://github.com/havelessbemore/dastal/blob/dba59a5/src/list/list.ts#L219) ___ @@ -472,7 +502,7 @@ Update the elements of the list The list on which this method was called -Defined in: [src/list/list.ts:220](https://github.com/havelessbemore/dastal/blob/0f470df/src/list/list.ts#L220) +Defined in: [src/list/list.ts:227](https://github.com/havelessbemore/dastal/blob/dba59a5/src/list/list.ts#L227) ▸ **update**(`min`: *undefined* \| *number*, `callback`: (`element`: T, `index`: *number*) => T): [*List*](list.md) @@ -492,7 +522,7 @@ end of the list. For example, -2 refers to the second to last element of the lis The list on which this method was called -Defined in: [src/list/list.ts:232](https://github.com/havelessbemore/dastal/blob/0f470df/src/list/list.ts#L232) +Defined in: [src/list/list.ts:239](https://github.com/havelessbemore/dastal/blob/dba59a5/src/list/list.ts#L239) ▸ **update**(`min`: *undefined* \| *number*, `max`: *undefined* \| *number*, `callback`: (`element`: T, `index`: *number*) => T): [*List*](list.md) @@ -513,7 +543,7 @@ end of the list. For example, -2 refers to the second to last element of the lis The list on which this method was called -Defined in: [src/list/list.ts:245](https://github.com/havelessbemore/dastal/blob/0f470df/src/list/list.ts#L245) +Defined in: [src/list/list.ts:252](https://github.com/havelessbemore/dastal/blob/dba59a5/src/list/list.ts#L252) ___ @@ -539,4 +569,4 @@ end of the list. For example, -2 refers to the second to last element of the lis An iterator through the indicated section of the list -Defined in: [src/list/list.ts:263](https://github.com/havelessbemore/dastal/blob/0f470df/src/list/list.ts#L263) +Defined in: [src/list/list.ts:270](https://github.com/havelessbemore/dastal/blob/dba59a5/src/list/list.ts#L270) diff --git a/docs/interfaces/queue.md b/docs/interfaces/queue.md index 03149af..e362f31 100644 --- a/docs/interfaces/queue.md +++ b/docs/interfaces/queue.md @@ -1,4 +1,4 @@ -[dastal - v1.3.1](../README.md) / Queue +[dastal - v1.4.0](../README.md) / Queue # Interface: Queue @@ -51,7 +51,7 @@ Every implementation should specify its ordering properties. Otherwise, insertio The number of elements in this queue -Defined in: [src/queue/queue.ts:40](https://github.com/havelessbemore/dastal/blob/0f470df/src/queue/queue.ts#L40) +Defined in: [src/queue/queue.ts:40](https://github.com/havelessbemore/dastal/blob/dba59a5/src/queue/queue.ts#L40) ## Methods @@ -75,7 +75,7 @@ Removes all elements from this queue **Returns:** *void* -Defined in: [src/queue/queue.ts:16](https://github.com/havelessbemore/dastal/blob/0f470df/src/queue/queue.ts#L16) +Defined in: [src/queue/queue.ts:16](https://github.com/havelessbemore/dastal/blob/dba59a5/src/queue/queue.ts#L16) ___ @@ -89,7 +89,7 @@ Retrieves and removes the head of this queue The value at the head of the queue or `undefined` if this queue is empty. -Defined in: [src/queue/queue.ts:22](https://github.com/havelessbemore/dastal/blob/0f470df/src/queue/queue.ts#L22) +Defined in: [src/queue/queue.ts:22](https://github.com/havelessbemore/dastal/blob/dba59a5/src/queue/queue.ts#L22) ___ @@ -109,7 +109,7 @@ Inserts the specified value into this queue The new size of the queue -Defined in: [src/queue/queue.ts:30](https://github.com/havelessbemore/dastal/blob/0f470df/src/queue/queue.ts#L30) +Defined in: [src/queue/queue.ts:30](https://github.com/havelessbemore/dastal/blob/dba59a5/src/queue/queue.ts#L30) ___ @@ -123,4 +123,4 @@ Retrieves, but does not remove, the head of this queue The value at the head of the queue or `undefined` if this queue is empty. -Defined in: [src/queue/queue.ts:36](https://github.com/havelessbemore/dastal/blob/0f470df/src/queue/queue.ts#L36) +Defined in: [src/queue/queue.ts:36](https://github.com/havelessbemore/dastal/blob/dba59a5/src/queue/queue.ts#L36) diff --git a/docs/interfaces/sortable.md b/docs/interfaces/sortable.md new file mode 100644 index 0000000..6629b07 --- /dev/null +++ b/docs/interfaces/sortable.md @@ -0,0 +1,43 @@ +[dastal - v1.4.0](../README.md) / Sortable + +# Interface: Sortable + +Represents an object containing a set of elements that can be sorted. + +## Type parameters + +| Name | +| :------ | +| `T` | + +## Hierarchy + +* **Sortable** + + ↳ [*List*](list.md) + +## Table of contents + +### Methods + +- [sort](sortable.md#sort) + +## Methods + +### sort + +▸ **sort**(`compareFn`: [*CompareFn*](../README.md#comparefn)): [*Sortable*](sortable.md) + +Sorts the elements in place. + +#### Parameters: + +| Name | Type | Description | +| :------ | :------ | :------ | +| `compareFn` | [*CompareFn*](../README.md#comparefn) | A function used to determine the order of elements. It is expected to return: - A negative value if first argument < second argument - Zero if first argument == second argument - A positive value if first argument > second argument | + +**Returns:** [*Sortable*](sortable.md) + +The object this method was called on + +Defined in: [src/index.ts:38](https://github.com/havelessbemore/dastal/blob/dba59a5/src/index.ts#L38) diff --git a/docs/interfaces/sorted.md b/docs/interfaces/sorted.md new file mode 100644 index 0000000..4a25ab5 --- /dev/null +++ b/docs/interfaces/sorted.md @@ -0,0 +1,35 @@ +[dastal - v1.4.0](../README.md) / Sorted + +# Interface: Sorted + +Represents an object containing a set of sorted elements. + +## Type parameters + +| Name | +| :------ | +| `T` | + +## Hierarchy + +* **Sorted** + + ↳ [*Heap*](heap.md) + +## Table of contents + +### Methods + +- [comparator](sorted.md#comparator) + +## Methods + +### comparator + +▸ **comparator**(): [*CompareFn*](../README.md#comparefn) + +**Returns:** [*CompareFn*](../README.md#comparefn) + +The function with which elements are sorted + +Defined in: [src/index.ts:47](https://github.com/havelessbemore/dastal/blob/dba59a5/src/index.ts#L47) diff --git a/docs/interfaces/stack.md b/docs/interfaces/stack.md index 9986822..f1971b0 100644 --- a/docs/interfaces/stack.md +++ b/docs/interfaces/stack.md @@ -1,4 +1,4 @@ -[dastal - v1.3.1](../README.md) / Stack +[dastal - v1.4.0](../README.md) / Stack # Interface: Stack @@ -50,7 +50,7 @@ Every implementation should specify its ordering properties. Otherwise, insertio The number of elements in the stack -Defined in: [src/stack/stack.ts:39](https://github.com/havelessbemore/dastal/blob/0f470df/src/stack/stack.ts#L39) +Defined in: [src/stack/stack.ts:39](https://github.com/havelessbemore/dastal/blob/dba59a5/src/stack/stack.ts#L39) ## Methods @@ -74,7 +74,7 @@ Removes all elements from the stack **Returns:** *void* -Defined in: [src/stack/stack.ts:15](https://github.com/havelessbemore/dastal/blob/0f470df/src/stack/stack.ts#L15) +Defined in: [src/stack/stack.ts:15](https://github.com/havelessbemore/dastal/blob/dba59a5/src/stack/stack.ts#L15) ___ @@ -88,7 +88,7 @@ Retrieves, but does not remove, the top of the stack The element at the top of the stack or `undefined` if empty. -Defined in: [src/stack/stack.ts:21](https://github.com/havelessbemore/dastal/blob/0f470df/src/stack/stack.ts#L21) +Defined in: [src/stack/stack.ts:21](https://github.com/havelessbemore/dastal/blob/dba59a5/src/stack/stack.ts#L21) ___ @@ -102,7 +102,7 @@ Retrieves and removes the top of the stack The element at the top of the stack or `undefined` if empty. -Defined in: [src/stack/stack.ts:27](https://github.com/havelessbemore/dastal/blob/0f470df/src/stack/stack.ts#L27) +Defined in: [src/stack/stack.ts:27](https://github.com/havelessbemore/dastal/blob/dba59a5/src/stack/stack.ts#L27) ___ @@ -122,4 +122,4 @@ Inserts an element into the stack The new size of the stack -Defined in: [src/stack/stack.ts:35](https://github.com/havelessbemore/dastal/blob/0f470df/src/stack/stack.ts#L35) +Defined in: [src/stack/stack.ts:35](https://github.com/havelessbemore/dastal/blob/dba59a5/src/stack/stack.ts#L35) diff --git a/src/array/bigArray.ts b/src/TODO/array/bigArray.ts similarity index 100% rename from src/array/bigArray.ts rename to src/TODO/array/bigArray.ts diff --git a/src/TODO/array/index.ts b/src/TODO/array/index.ts new file mode 100644 index 0000000..cbc2fed --- /dev/null +++ b/src/TODO/array/index.ts @@ -0,0 +1 @@ +export * from './bigArray'; diff --git a/src/math/bits.ts b/src/TODO/math/bits.ts similarity index 99% rename from src/math/bits.ts rename to src/TODO/math/bits.ts index 907710b..ad631da 100644 --- a/src/math/bits.ts +++ b/src/TODO/math/bits.ts @@ -12,7 +12,6 @@ export function lsb(a: number): number { } return b; } - /** * Get the Least Significant Power of a number * @@ -23,7 +22,6 @@ export function lsb(a: number): number { export function lsp(a: number): number { return (a & -a) >>> 0; } - /** * Get the number of bits set (on) of a number * @@ -37,7 +35,6 @@ export function onBits(a: number): number { } return b; } - /** * Get the Most Significant Bit of a number * @@ -53,7 +50,6 @@ export function msb(a: number): number { } return b; } - /** * Get the Most Significant Power of a number * diff --git a/src/math/index.ts b/src/TODO/math/index.ts similarity index 100% rename from src/math/index.ts rename to src/TODO/math/index.ts diff --git a/src/segmentTree/inOrderSegmentTree.ts b/src/TODO/segmentTree/inOrderSegmentTree.ts similarity index 87% rename from src/segmentTree/inOrderSegmentTree.ts rename to src/TODO/segmentTree/inOrderSegmentTree.ts index 32f4064..a963a9e 100644 --- a/src/segmentTree/inOrderSegmentTree.ts +++ b/src/TODO/segmentTree/inOrderSegmentTree.ts @@ -1,7 +1,8 @@ -import { LinkedList } from '../list/linkedList'; +import { LinkedList } from '../../list/linkedList'; import { lsb, lsp, msb, msp } from '../math/bits'; import { LazyOperation, Operation, SegmentTree } from './segmentTree'; import { CombineFn } from '.'; +import { MAX_ARRAY_LENGTH } from 'src/array/utils'; /* mca(a, b) = lsp(a | msp(b - a)) ; // where a <= b @@ -20,31 +21,23 @@ export class InOrderSegmentTree implements SegmentTree { /** * The maximum amount of elements that can be added. * - * According to [ECMA-262](https://tc39.es/ecma262/#array-index): - * 0 <= array.length <= 2^32 - 1 - * - * Because n elements require 2n memory: - * 0 <= size <= 2^31 - 1 + * n elements require 2n memory. */ - static readonly MAX_SIZE: number = 2147483647; - + static readonly MAX_SIZE: number = MAX_ARRAY_LENGTH >>> 1; /** * The set of elements and aggregation nodes for the tree */ protected array: T[]; - /** * The function used to aggregate elements */ protected combine: CombineFn; - /** * The set of pending operations to perform on element ranges */ protected lazy: (LinkedList> | undefined)[]; - /** - * Construct a new {@link InOrderSegmentTree} + * Construct a new segment tree * * @param combine - The function used to aggregate segment information * @param elements - A set of elements to add into the initial tree @@ -56,84 +49,10 @@ export class InOrderSegmentTree implements SegmentTree { this.build(elements); } - /** - * A helper method used to build the tree - * - * @param elements The initial set of elements to add into the tree - */ - protected build(elements: Iterable) { - for (const element of elements) { - this.push(element); - } - } - - /** - * Remove all elements - */ clear(): void { this.array.length = 0; this.lazy.length = 0; } - - protected lazyPropagate(min: number, max: number): void { - // (a +1) & -(a + 1) - const stack: number[] = []; - - // Get top complete aggregation nodes in the range - // for (let i = msp(min); i < max; stack.push(i - 1)) { - // i += lsp(i | msp(this.array.length - i)); - // } - - // Get top complete aggregation nodes in the range in reverse - - // Iterate through the range, jumping across the largest possible subranges - do { - const offset = lsp(min | msp(max - min)); - const mid = min + (offset >>> 1) - 1; - min += offset; - - // Apply updates down to the current subrange - do { - const par = stack.pop()!; - if (this.lazy[par]) { - } - } while (true); - - // let value = operation(this.array[top], min >>> 1, (min + offset) >>> 1); - } while (min < max); - - throw new Error('Figure out initial i'); - /* - let i = msp(max); - for (i = lsp(i | msp(this.array.length - i)); i > min; i -= i & -i) { - stack.push(i - (lsp(i) >>> 1) - 1); - } - - // Take the longest possible jumps from min to max - while (min < max) { - const offset = lsp(min | msp(max - min)); - min += offset; - - const i = min - 1 + (offset >>> 1); - - - } - */ - - // Check each level - - /* - // Get existing - const q = []; - for (let i = min; i < max; ) { - const offset = lsp(min | msp(max - min)); - i += offset; - } - - max = msb(min ^ this.array.length) - lsb(min); - */ - } - /** * Lazily updates elements in a given range * @@ -195,11 +114,6 @@ export class InOrderSegmentTree implements SegmentTree { this.array[min] = value; } - /** - * Remove the last added element - * - * @returns The last added element or `undefined` if empty. - */ pop(): T | undefined { // Sanitize range if (this.size < 1) { @@ -219,12 +133,6 @@ export class InOrderSegmentTree implements SegmentTree { return out; } - /** - * Insert the given element into the end of the tree - * - * @param element - The element to be inserted - * - */ push(element: T): number { // Sanitize range if (this.size >= InOrderSegmentTree.MAX_SIZE) { @@ -247,14 +155,6 @@ export class InOrderSegmentTree implements SegmentTree { return this.size; } - /** - * Get the aggregated information for elements in a given range - * - * @param min - The start of the range, inclusive - * @param max - The end of the range, exclusive - * - * @returns The aggregated information for elements in range [min, max) - */ query(min: number, max: number): T { // Sanitize range if (min >= max) { @@ -283,10 +183,6 @@ export class InOrderSegmentTree implements SegmentTree { return value; } - /** - * The number of elements in the tree: - * 0 <= size <= {@link MAX_SIZE} - */ get size(): number { return this.array.length >>> 1; } @@ -300,13 +196,6 @@ export class InOrderSegmentTree implements SegmentTree { } } - /** - * Update elements in a given range - * - * @param min - The start of the range, inclusive - * @param max - The end of the range, exclusive - * @param operation - The operation to perform on the range - */ update(min: number, max: number, operation: Operation): void { // Sanitize range if (min >= max) { @@ -349,4 +238,73 @@ export class InOrderSegmentTree implements SegmentTree { // Update the incomplete aggregation node this.array[min] = value; } + /** + * A helper method used to build the tree + * + * @param elements The initial set of elements to add into the tree + */ + protected build(elements: Iterable) { + for (const element of elements) { + this.push(element); + } + } + + protected lazyPropagate(min: number, max: number): void { + // (a +1) & -(a + 1) + const stack: number[] = []; + + // Get top complete aggregation nodes in the range + // for (let i = msp(min); i < max; stack.push(i - 1)) { + // i += lsp(i | msp(this.array.length - i)); + // } + + // Get top complete aggregation nodes in the range in reverse + + // Iterate through the range, jumping across the largest possible subranges + do { + const offset = lsp(min | msp(max - min)); + const mid = min + (offset >>> 1) - 1; + min += offset; + + // Apply updates down to the current subrange + do { + const par = stack.pop()!; + if (this.lazy[par]) { + } + } while (true); + + // let value = operation(this.array[top], min >>> 1, (min + offset) >>> 1); + } while (min < max); + + throw new Error('Figure out initial i'); + /* + let i = msp(max); + for (i = lsp(i | msp(this.array.length - i)); i > min; i -= i & -i) { + stack.push(i - (lsp(i) >>> 1) - 1); + } + + // Take the longest possible jumps from min to max + while (min < max) { + const offset = lsp(min | msp(max - min)); + min += offset; + + const i = min - 1 + (offset >>> 1); + + + } + */ + + // Check each level + + /* + // Get existing + const q = []; + for (let i = min; i < max; ) { + const offset = lsp(min | msp(max - min)); + i += offset; + } + + max = msb(min ^ this.array.length) - lsb(min); + */ + } } diff --git a/src/segmentTree/index.ts b/src/TODO/segmentTree/index.ts similarity index 100% rename from src/segmentTree/index.ts rename to src/TODO/segmentTree/index.ts diff --git a/src/segmentTree/levelOrderSegmentTree.ts b/src/TODO/segmentTree/levelOrderSegmentTree.ts similarity index 85% rename from src/segmentTree/levelOrderSegmentTree.ts rename to src/TODO/segmentTree/levelOrderSegmentTree.ts index 7f9c681..ed1a603 100644 --- a/src/segmentTree/levelOrderSegmentTree.ts +++ b/src/TODO/segmentTree/levelOrderSegmentTree.ts @@ -1,3 +1,4 @@ +import { MAX_ARRAY_LENGTH } from 'src/array/utils'; import { CombineFn } from '.'; import { lsp, msb, msp } from '../math/bits'; import { LazyOperation, Operation, SegmentTree } from './segmentTree'; @@ -10,34 +11,25 @@ export class LevelOrderSegmentTree implements SegmentTree { /** * The maximum number of elements that can be added. * - * According to [ECMA-262](https://tc39.es/ecma262/#array-index): - * 0 <= array.length <= 2^32 - 1 - * - * So since n elements require 2^⌊log2(2n)⌋ - 1 memory: - * 0 <= size <= 2^31 + * n elements require 2^⌈log2(2n)⌉ - 1 memory: */ - static readonly MAX_SIZE: number = 2147483648; - + static readonly MAX_SIZE: number = (MAX_ARRAY_LENGTH + 1) / 2; /** * The internal array used to store elements and aggregation nodes */ protected array: Array; - /** * The function used to aggregate elements */ protected combine: CombineFn; - /** * The used length (size) of our internal array */ protected length: number; - /** * The start index for the lowest level */ protected level: number; - /** * Construct a new {@link SegmentTree} * @@ -52,118 +44,12 @@ export class LevelOrderSegmentTree implements SegmentTree { this.build(elements); } - /** - * A helper method used to build the tree - * - * @param elements The initial set of elements to add into the tree - */ - protected build(elements: Iterable): void { - let key = ''; - - // Check if the iterable's size can be known. - // For example: array.length or map.size - if ('length' in elements && typeof elements['length'] !== 'number') { - key = 'length'; - } else if ('size' in elements && typeof elements['size'] !== 'number') { - key = 'size'; - } - - // Iterate normally if size is not given - if (key.length < 1) { - for (const element of elements) { - this.push(element); - } - return; - } - - // Get the iterable's size - const n = (elements as any)[key]; - - // Check for base case - if (n < 1) { - this.array.length = 0; - this.length = 0; - this.level = 0; - return; - } - - // Check if max capacity reached - if (n >= LevelOrderSegmentTree.MAX_SIZE) { - throw new RangeError(`Invalid SegmentTree length`); - } - - // Allocate the array - this.level = 2 * msp(n - 1) - 1; - this.length = this.level + n; - this.array.length = 2 * this.level + 1; - - // Build the tree - const it = elements[Symbol.iterator](); - this.update(0, n, (_) => it.next().value); - } - - /** - * Shift the tree down a level - */ - protected grow(): void { - // Check if max capacity reached - if (this.size >= LevelOrderSegmentTree.MAX_SIZE) { - throw new RangeError(`Invalid SegmentTree length`); - } - - // Extend capacity - this.array.length += this.array.length + 1; - - // Shift the tree down a level - let min = this.level + 1; - for (let max = this.length + 1; min < max; max >>>= 1) { - this.array.copyWithin(2 * min - 1, min - 1, max - 1); - min >>>= 1; - } - - // Update pointers - this.length += this.level + 1; - this.level += this.level + 1; - } - - /** - * Shift the tree up a level - */ - protected shrink(): void { - // Get the tree's Lowest Common Ancestor (root) - let min = this.level + 1; - let max = msb(min ^ this.length) + 1; - min >>>= max; - - // Shift the tree up a level - ++this.level; - if (min > 0) { - for (max = min + 1; min <= this.level; max *= 2) { - this.array.copyWithin((min >>> 1) - 1, min - 1, max - 1); - min *= 2; - } - } - - // Update pointers and capacity - this.level -= (this.level >>> 1) + 1; - this.length -= (this.length + 1) >>> 1; - this.array.length = this.length - this.level + this.length; - } - - /** - * Remove all elements - */ clear(): void { this.length = 0; this.level = 0; this.array.length = 0; } - /** - * Remove the last added element - * - * @returns The last added element or `undefined` if empty. - */ pop(): T | undefined { // Sanitize range if (this.length <= this.level) { @@ -181,11 +67,6 @@ export class LevelOrderSegmentTree implements SegmentTree { return out; } - /** - * Insert the given element into the end of the tree - * - * @param element - The element to be inserted - */ push(element: T): number { // If array is full if (this.length >= this.array.length) { @@ -204,14 +85,6 @@ export class LevelOrderSegmentTree implements SegmentTree { return this.size; } - /** - * Get the aggregated information for elements in a given range - * - * @param min - The start of the range, inclusive - * @param max - The end of the range, exclusive - * - * @returns The aggregated information for elements in range [min, max) - */ query(min: number, max: number): T { // Sanitize range if (min >= max) { @@ -240,10 +113,6 @@ export class LevelOrderSegmentTree implements SegmentTree { return value; } - /** - * The number of elements in the tree: - * 0 <= size <= {@link MAX_SIZE} - */ get size(): number { return this.length - this.level; } @@ -257,13 +126,6 @@ export class LevelOrderSegmentTree implements SegmentTree { } } - /** - * Update elements in a given range - * - * @param min - The start of the range, inclusive - * @param max - The end of the range, exclusive - * @param operation - The operation to perform on the range - */ update(min: number, max: number, operation: Operation): void { // Sanitize range if (min >= max) { @@ -294,4 +156,100 @@ export class LevelOrderSegmentTree implements SegmentTree { max >>>= 1; } } + + /** + * A helper method used to build the tree + * + * @param elements The initial set of elements to add into the tree + */ + protected build(elements: Iterable): void { + let key = ''; + + // Check if the iterable's size can be known. + // For example: array.length or map.size + if ('length' in elements && typeof elements['length'] !== 'number') { + key = 'length'; + } else if ('size' in elements && typeof elements['size'] !== 'number') { + key = 'size'; + } + + // Iterate normally if size is not given + if (key.length < 1) { + for (const element of elements) { + this.push(element); + } + return; + } + + // Get the iterable's size + const n = (elements as any)[key]; + + // Check for base case + if (n < 1) { + this.array.length = 0; + this.length = 0; + this.level = 0; + return; + } + + // Check if max capacity reached + if (n >= LevelOrderSegmentTree.MAX_SIZE) { + throw new RangeError(`Invalid SegmentTree length`); + } + + // Allocate the array + this.level = 2 * msp(n - 1) - 1; + this.length = this.level + n; + this.array.length = 2 * this.level + 1; + + // Build the tree + const it = elements[Symbol.iterator](); + this.update(0, n, (_) => it.next().value); + } + /** + * Shift the tree down a level + */ + protected grow(): void { + // Check if max capacity reached + if (this.size >= LevelOrderSegmentTree.MAX_SIZE) { + throw new RangeError(`Invalid SegmentTree length`); + } + + // Extend capacity + this.array.length += this.array.length + 1; + + // Shift the tree down a level + let min = this.level + 1; + for (let max = this.length + 1; min < max; max >>>= 1) { + this.array.copyWithin(2 * min - 1, min - 1, max - 1); + min >>>= 1; + } + + // Update pointers + this.length += this.level + 1; + this.level += this.level + 1; + } + /** + * Shift the tree up a level + */ + protected shrink(): void { + // Get the tree's Lowest Common Ancestor (root) + let min = this.level + 1; + let max = msb(min ^ this.length) + 1; + min >>>= max; + + // Shift the tree up a level + ++this.level; + if (min > 0) { + for (max = min + 1; min <= this.level; max *= 2) { + this.array.copyWithin((min >>> 1) - 1, min - 1, max - 1); + min *= 2; + } + } + + // Update pointers and capacity + this.level -= (this.level >>> 1) + 1; + this.length -= (this.length + 1) >>> 1; + this.array.length = this.length - this.level + this.length; + } } diff --git a/src/segmentTree/postOrderSegmentTree.ts b/src/TODO/segmentTree/postOrderSegmentTree.ts similarity index 99% rename from src/segmentTree/postOrderSegmentTree.ts rename to src/TODO/segmentTree/postOrderSegmentTree.ts index a1f2b41..0228182 100644 --- a/src/segmentTree/postOrderSegmentTree.ts +++ b/src/TODO/segmentTree/postOrderSegmentTree.ts @@ -9,22 +9,28 @@ export class PostOrderSegmentTree implements SegmentTree { this.array = []; this.length = 0; } + clear(): void { this.array.length = 0; this.length = 0; } + pop(): T | undefined { throw new Error('TODO'); } + push(element: T): number { throw new Error('TODO'); } + query(min: number, max: number): T { throw new Error('TODO'); } + get size(): number { throw new Error('TODO'); } + *[Symbol.iterator](): Iterator { let i = 0; for (let j = 0; j < this.length; j = 2 * i - onBits(i)) { @@ -32,6 +38,7 @@ export class PostOrderSegmentTree implements SegmentTree { ++i; } } + update(min: number, max: number, operation: Operation): void { throw new Error('TODO'); } diff --git a/src/segmentTree/segmentTree.ts b/src/TODO/segmentTree/segmentTree.ts similarity index 94% rename from src/segmentTree/segmentTree.ts rename to src/TODO/segmentTree/segmentTree.ts index c4e072f..5cd394e 100644 --- a/src/segmentTree/segmentTree.ts +++ b/src/TODO/segmentTree/segmentTree.ts @@ -6,12 +6,6 @@ export interface Operation { (element: T, index: number): T; } -/* -export interface Combinator { - combine: CombineFn; -} -*/ - export interface CombineFn { (a: T, b: T): K; } diff --git a/src/trie/genericTrie.ts b/src/TODO/trie/genericTrie.ts similarity index 100% rename from src/trie/genericTrie.ts rename to src/TODO/trie/genericTrie.ts diff --git a/src/trie/index.ts b/src/TODO/trie/index.ts similarity index 100% rename from src/trie/index.ts rename to src/TODO/trie/index.ts diff --git a/src/trie/prefixTrie.ts b/src/TODO/trie/prefixTrie.ts similarity index 100% rename from src/trie/prefixTrie.ts rename to src/TODO/trie/prefixTrie.ts diff --git a/src/trie/suffixTrie.ts b/src/TODO/trie/suffixTrie.ts similarity index 100% rename from src/trie/suffixTrie.ts rename to src/TODO/trie/suffixTrie.ts diff --git a/src/trie/trie.ts b/src/TODO/trie/trie.ts similarity index 100% rename from src/trie/trie.ts rename to src/TODO/trie/trie.ts diff --git a/src/array/utils.ts b/src/array/utils.ts new file mode 100644 index 0000000..de019ba --- /dev/null +++ b/src/array/utils.ts @@ -0,0 +1,7 @@ +/** + * The maximum length of an array. + * + * According to [ECMA-262](https://tc39.es/ecma262/#array-index): + * 0 <= array.length <= 2^32 - 1 + */ +export const MAX_ARRAY_LENGTH = 4294967295; diff --git a/src/heap/binaryHeap.ts b/src/heap/binaryHeap.ts index 8f73faa..f052909 100644 --- a/src/heap/binaryHeap.ts +++ b/src/heap/binaryHeap.ts @@ -1,5 +1,7 @@ +import { MAX_ARRAY_LENGTH } from 'src/array/utils'; import { CompareFn } from '..'; import { Heap } from './heap'; +import { SkewHeap } from './skewHeap'; import { bubbleUp, heapify, sinkDown } from './utils'; /** @@ -7,18 +9,43 @@ import { bubbleUp, heapify, sinkDown } from './utils'; */ export class BinaryHeap implements Heap { /** - * @ignore + * The array containing every element. */ protected array: T[]; /** - * @ignore + * The function to determine the order of elements. */ protected compare: CompareFn; - + /** + * Instantiate a heap. + * + * @param compareFn - The function to determine the order of elements. + * @param elements - A set of elements to initialize the list with. + */ constructor(compareFn: CompareFn, elements?: Iterable) { this.compare = compareFn; - this.array = Array.from(elements ?? []); - heapify(this.compare, this.array); + this.array = []; + this.addAll(elements ?? []); + } + + addAll(elements: Iterable): number { + const array = this.array; + + // Add new elements + const length = array.length; + for (const element of elements) { + if (array.length >= MAX_ARRAY_LENGTH) { + throw new RangeError('Invalid heap length'); + } + array.push(element); + } + + // Update the heap + if (length < array.length) { + heapify(this.compare, array); + } + + return array.length; } clear(): void { @@ -54,26 +81,28 @@ export class BinaryHeap implements Heap { } *dump(): Iterable { - for (let i = 0; i < this.array.length; ++i) { - yield this.array[i]; + for (const value of this.array) { + yield value; } } - merge(elements: Iterable): number { + merge(heap: Heap): this { const array = this.array; - const length = array.length; - try { - for (const element of elements) { - array.push(element); - } - } catch (error) { - throw error; - } finally { - if (length != array.length) { - heapify(this.compare, array); - } + + if (heap.size < 1) { + return this; } - return this.size; + if (array.length + heap.size > MAX_ARRAY_LENGTH) { + throw new RangeError('Invalid heap length'); + } + + const elements = heap instanceof BinaryHeap ? heap.array : heap.dump(); + for (const element of elements) { + array.push(element); + } + + heapify(this.compare, array); + return this; } peek(): T | undefined { @@ -91,8 +120,7 @@ export class BinaryHeap implements Heap { // If value != last if (this.array.length > 0) { - // Add the last value to - // the root and update the heap + // Move the last value to the root and update the heap this.array[0] = last!; sinkDown(0, this.compare, this.array); } @@ -109,9 +137,8 @@ export class BinaryHeap implements Heap { return this.size; } - // Push a new value to the heap and then pop the root pushPop(value: T): T { - // If empty or value is above or equal to root + // If empty or value is <= to root if (this.array.length < 1 || this.compare(value, this.array[0]) <= 0) { return value; } @@ -123,7 +150,6 @@ export class BinaryHeap implements Heap { return root; } - // Pop the root of the heap and then push a new value replace(value: T): T | undefined { // If empty if (this.array.length < 1) { @@ -138,16 +164,34 @@ export class BinaryHeap implements Heap { // Update the heap sinkDown(0, this.compare, this.array); - return value; } get size(): number { return this.array.length; } - - [Symbol.iterator](): Iterator { - return Array.from(this.array).sort(this.compare)[Symbol.iterator](); + /** + * Iterate through the heap in sorted order. + * + * **Note:** Unexpected behavior can occur if the collection is modified during iteration. + * + * @returns An iterator through the heap. + */ + *[Symbol.iterator](): Iterator { + if (this.array.length < 1) { + return; + } + const array = this.array; + const heap = new BinaryHeap((a, b) => this.compare(array[a], array[b]), [0]); + do { + let index = heap.pop()!; + if (index < array.length) { + yield array[index]; + index = 2 * index + 1; + index < array.length && heap.push(index); + ++index < array.length && heap.push(index); + } + } while (heap.size > 0); } update(curElement: T, newElement: T): boolean { diff --git a/src/heap/heap.ts b/src/heap/heap.ts index 4a6a8ac..365a624 100644 --- a/src/heap/heap.ts +++ b/src/heap/heap.ts @@ -1,77 +1,137 @@ import { Sorted } from '..'; /** + * A specialized tree-based data structure that satisfies the heap property. * + * **Heap property**: For any given node N, the key (e.g. value) of N is greater than or equal to the key of its children. + * + * In a heap, the highest priority element (relative to its ordering) is always stored at the root. + * However, a heap is not a sorted structure; it can be regarded as being partially ordered. + * The heap property only applies between a parent node and its descendants. There is no + * implied ordering between siblings or cousins and no implied sequence for an ordered traversal. + * + * A heap is a useful data structure when it is necessary to repeatedly + * remove the object with the highest priority. In the sense, it can be used to implement + * a priority queue. + * + * #### Iterate + * - Iterate the heap: {@link dump} + * - Iterate the heap in sorted order: {@link [Symbol.iterator]} + * + * #### Get + * - Get the size of the heap: {@link size} + * - Get the top element: {@link peek} + * - Check if the heap contains a given element: {@link contains} + * - Get the heap's sorting method: {@link comparator} + * + * #### Set + * - Update an element: {@link update} + * + * #### Add + * - Add 1 element: {@link push} + * - Add 1 heap: {@link merge} + * - Add multiple elements: {@link addAll} + * + * #### Remove + * - Remove the top element: {@link pop} + * - Delete a given element: {@link delete} + * - Remove all elements: {@link clear} + * + * #### Add and Remove + * - Add and then remove the top element: {@link pushPop} + * - Remove the top element and then add an element: {@link replace} */ export interface Heap extends Iterable, Sorted { /** + * Insert a set of elements into the heap. + * + * @param elements - The elements to insert. * + * @returns The new size of the list. + */ + addAll(elements: Iterable): number; + /** + * Remove all elements. */ clear(): void; /** + * Check if an element is in the heap. * - * @param element + * @param element - The element to find. + * + * @returns `true` if the element was found, otherwise `false`. */ contains(element: T): boolean; /** + * Delete an element from the heap. * - * Aka extract, remove - * @param element + * @param element - The element to delete. * - * @returns + * @returns `true` if the element was found and deleted, otherwise `false`. */ delete(element: T): boolean; /** + * Iterate through the heap. * + * **Note:** Unexpected behavior can occur if the collection is modified during iteration. */ dump(): Iterable; /** + * Join with a different heap and modify the existing heap to + * contain elements of both. Does not modify the input. + * + * @param heap - The heap to join with. * - * @param elements - * @returns + * @returns The new heap size. */ - merge(elements: Iterable): number; + merge(heap: Heap): this; /** + * Retrieves, but does not remove, the top of the heap. * - * @returns + * @returns The element at the top of the heap or `undefined` if empty. */ peek(): T | undefined; /** + * Remove the top of the heap (AKA extract). * - * @returns + * @returns The element at the top of the heap or `undefined` if empty. */ pop(): T | undefined; /** + * Inserts an element into the heap (AKA insert, add). * - * @param element + * @param element - The element to be inserted. * - * @returns + * @returns The new size of the heap. */ push(element: T): number; // Aka insert, add /** + * Insert an element and then remove the top of the heap. * - * @param element + * @param element - The element to be inserted. * - * @returns + * @returns The element at the top of the heap. */ pushPop(element: T): T; /** + * Remove the top of the heap and then insert a new element (AKA popPush). * - * @param element + * @param element - The element to be inserted. * - * @returns + * @returns The element at the top of the heap or `undefined` if empty. */ - replace(element: T): T | undefined; // Aka popPush + replace(element: T): T | undefined; /** - * + * The number of elements in the heap. */ readonly size: number; /** + * Update a specific element. * - * @param curElement - * @param newElement + * @param curElement - The element to update. + * @param newElement - The new element to insert. * - * @returns + * @returns `true` if curElement was found and updated, otherwise `false`. */ update(curElement: T, newElement: T): boolean; } diff --git a/src/heap/index.ts b/src/heap/index.ts index a275254..d417f5e 100644 --- a/src/heap/index.ts +++ b/src/heap/index.ts @@ -1,2 +1,3 @@ export * from './binaryHeap'; export * from './heap'; +export * from './skewHeap'; diff --git a/src/heap/skewHeap.ts b/src/heap/skewHeap.ts new file mode 100644 index 0000000..2153657 --- /dev/null +++ b/src/heap/skewHeap.ts @@ -0,0 +1,198 @@ +import { BinaryTreeNode } from 'src/tree'; +import { clone, preOrderTraverse, toBinaryTree } from 'src/tree/utils'; +import { CompareFn } from '..'; +import { BinaryHeap } from './binaryHeap'; +import { Heap } from './heap'; +import { skewMerge } from './utils'; + +/** + * + */ +export class SkewHeap implements Heap { + /** + * The function to determine the order of elements. + */ + protected compare: CompareFn; + /** + * The number of elements in the list. + */ + protected length: number; + /** + * The node at the "top" of the heap. + */ + protected root: BinaryTreeNode | undefined; + /** + * Instantiate a heap. + * + * @param compareFn - The function to determine the order of elements. + * @param elements - A set of elements to initialize the list with. + */ + constructor(compareFn: CompareFn, elements?: Iterable) { + this.compare = compareFn; + this.length = 0; + this.addAll(elements ?? []); + } + + addAll(elements: Iterable): number { + for (const element of elements) { + this.push(element); + } + return this.length; + } + + clear(): void { + this.length = 0; + this.root = undefined; + } + + comparator(): CompareFn { + return this.compare; + } + + contains(element: T): boolean { + for (const node of preOrderTraverse(this.root)) { + if (element === node.value) { + return true; + } + } + return false; + } + + delete(element: T): boolean { + if (this.root == null) { + return false; + } + if (this.root.value === element) { + this.pop()!; + return true; + } + for (const par of preOrderTraverse(this.root)) { + const key: keyof BinaryTreeNode | undefined = + par.left && par.left.value === element + ? 'left' + : par.right && par.right.value === element + ? 'right' + : undefined; + if (key != null) { + const node = par[key]!; + par[key] = skewMerge(this.compare, [node.left, node.right]); + --this.length; + return true; + } + } + return false; + } + + *dump(): Iterable { + for (const node of preOrderTraverse(this.root)) { + yield node.value; + } + } + + merge(heap: Heap): this { + if (heap instanceof SkewHeap) { + this.root = skewMerge(this.compare, [this.root, clone(heap.root)]); + this.length += heap.size; + } else if (heap instanceof BinaryHeap) { + this.root = skewMerge(this.compare, [this.root, toBinaryTree(heap['array'])!]); + this.length += heap.size; + } else { + this.addAll(heap.dump()); + } + return this; + } + + peek(): T | undefined { + return this.root?.value; + } + + pop(): T | undefined { + if (this.root == null) { + return undefined; + } + const value = this.root.value; + this.root = skewMerge(this.compare, [this.root.left, this.root.right]); + --this.length; + return value; + } + + push(value: T): number { + this.root = skewMerge(this.compare, [this.root, { value }]); + return ++this.length; + } + + pushPop(value: T): T { + this.push(value); + return this.pop()!; + } + + replace(value: T): T | undefined { + if (this.root == null) { + this.root = { value }; + this.length = 1; + return undefined; + } + const out = this.root.value; + this.root = skewMerge(this.compare, [this.root.left, this.root.right, { value }]); + return out; + } + + get size(): number { + return this.length; + } + /** + * Iterate through the heap in sorted order. + * + * **Note:** Unexpected behavior can occur if the collection is modified during iteration. + * + * @returns An iterator through the heap. + */ + *[Symbol.iterator](): Iterator { + if (this.root == null) { + return; + } + const heap = new SkewHeap>((a, b) => this.compare(a.value, b.value), [ + this.root, + ]); + do { + const node = heap.pop()!; + yield node.value; + node.left && heap.push(node.left); + node.right && heap.push(node.right); + } while (heap.size > 0); + } + + update(curElement: T, newElement: T): boolean { + if (this.root == null) { + return false; + } + if (this.root.value === curElement) { + this.root = skewMerge(this.compare, [ + this.root.left, + this.root.right, + { value: newElement }, + ]); + return true; + } + for (const par of preOrderTraverse(this.root)) { + const key: keyof BinaryTreeNode | undefined = + par.left && par.left.value === curElement + ? 'left' + : par.right && par.right.value === curElement + ? 'right' + : undefined; + if (key != null) { + const node = par[key]!; + par[key] = undefined; + this.root = skewMerge(this.compare, [ + this.root, + node.left, + node.right, + { value: newElement }, + ]); + return true; + } + } + return false; + } +} diff --git a/src/heap/utils.ts b/src/heap/utils.ts index 1937710..d3c22e0 100644 --- a/src/heap/utils.ts +++ b/src/heap/utils.ts @@ -1,7 +1,9 @@ +import { LinkedList } from 'src/list'; +import { BinaryTreeNode } from 'src/tree'; import { CompareFn } from '..'; /** - * @ignore + * @internal */ export function bubbleUp(index: number, compareFn: CompareFn, array: Array): void { const value = array[index]; @@ -24,13 +26,13 @@ export function bubbleUp(index: number, compareFn: CompareFn, array: Array } } /** - * @ignore + * @internal */ export function heapify(compareFn: CompareFn, array: T[]): void { for (let i = (array.length + 1) >>> 1; i > 0; sinkDown(--i, compareFn, array)) {} } /** - * @ignore + * @internal */ export function sinkDown(index: number, compareFn: CompareFn, array: Array): void { const n = array.length; @@ -49,7 +51,6 @@ export function sinkDown(index: number, compareFn: CompareFn, array: Array if (childIndex + 1 < n && compareFn(array[childIndex + 1], child) <= 0) { child = array[++childIndex]!; } - //console.log(value, child); // If value <= child if (compareFn(value, child) <= 0) { @@ -62,3 +63,60 @@ export function sinkDown(index: number, compareFn: CompareFn, array: Array index = childIndex; } while (true); } +/** + * See: https://en.wikipedia.org/wiki/Skew_heap#Merging_two_heaps + * + * @param compareFn - A function used to determine the order of the heap. + * + * It is expected to return: + * - A negative value if first argument < second argument + * - Zero if first argument == second argument + * - A positive value if first argument > second argument + * @param heaps - An iterable of heaps to merge + * + * @returns The new heap + */ +export function skewMerge( + compareFn: CompareFn, + heaps: Iterable | undefined>, +): BinaryTreeNode | undefined { + // Sanitize inputs + const list = new LinkedList>(); + for (const node of heaps) { + if (node != null) { + list.push(node); + } + } + if (list.size < 2) { + return list.pop()!; + } + + // Split each heap into subtrees by cutting every path. + // (From the root node, sever the right node and make the right + // child its own subtree.) This will result in a set of trees + // in which the root either only has a left child or no children at all. + for (const node of list) { + if (node.right != null) { + list.push(node.right); + node.right = undefined; + } + } + + // Sort the subtrees in descending order based on the + // value of the root node of each subtree. + list.sort((a, b) => compareFn(b.value, a.value)); + + // While there are still multiple subtrees, iteratively recombine + // the first two (from left to right). If the root of the second-to-first + // subtree has a left child, swap it to be the right child. Link the root + // of the last subtree as the left child of the second-to-first subtree. + let heap = list.shift()!; + do { + const next = list.shift()!; + next.right = next.left; + next.left = heap; + heap = next; + } while (list.size > 0); + + return heap; +} diff --git a/src/index.ts b/src/index.ts index ac21381..59af748 100644 --- a/src/index.ts +++ b/src/index.ts @@ -8,41 +8,41 @@ export * from './stack'; // export * from './trie'; /** + * A function used to determine the order of a set of elements. * + * @param a - The first element + * @param b - The second element + * + * @returns + * - A negative value if a < b + * - Zero if a == b + * - A positive value if a > b */ -export interface CompareFn { - /** - * - */ - (a: T, b: T): number; -} - +export type CompareFn = (a: T, b: T) => number; /** - * + * Represents an object containing a set of elements that can be sorted. */ export interface Sortable { /** + * Sorts the elements in place. * - */ - sort: SortFn; -} - -/** - * - */ -export interface SortFn { - /** + * @param compareFn - A function used to determine the order of elements. * + * It is expected to return: + * - A negative value if first argument < second argument + * - Zero if first argument == second argument + * - A positive value if first argument > second argument + * + * @returns The object this method was called on */ - (compareFn: CompareFn): void; + sort(compareFn: CompareFn): this; } - /** - * + * Represents an object containing a set of sorted elements. */ export interface Sorted { /** - * + * @returns The function with which elements are sorted */ comparator(): CompareFn; } diff --git a/src/list/arrayList.ts b/src/list/arrayList.ts index c3e88e6..fb37186 100644 --- a/src/list/arrayList.ts +++ b/src/list/arrayList.ts @@ -1,40 +1,31 @@ +import { CompareFn } from '..'; import { List } from './list'; -import { batch, clamp, wrap } from './utils'; +import { batch, clamp, cwrap } from './utils'; /** * An implementation of the {@link List} interface using an array */ export class ArrayList implements List { /** - * @ignore + * The array containing every element. */ protected array: Array; - - constructor(elements?: Iterable) { - this.array = elements ? Array.from(elements) : []; - } /** - * Add the element at the specified index. + * Instantiate the list. * - * @param index - The index to add into - * @param element - The element to add - * - * @returns The new size of the list + * @param elements - A set of elements to initialize the list with. */ + constructor(elements?: Iterable) { + this.array = elements ? Array.from(elements) : []; + } + add(index: number, element: T): number { if (index >= 0 && index <= this.size) { this.array.splice(index, 0, element); } return this.size; } - /** - * Add elements at the specified index. - * - * @param index - The index to add into - * @param element - The elements to add - * - * @returns The new size of the list - */ + addAll(index: number, elements: Iterable): number { if (index >= 0 && index <= this.size) { for (const items of batch(10000, elements)) { @@ -44,22 +35,11 @@ export class ArrayList implements List { } return this.size; } - /** - * Removes all elements - */ + clear(): void { this.array.length = 0; } - /** - * Combines the list with multiple iterables into a new list. - * Does not modify the existing list or inputs. - * - * @param lists — Additional iterables to add to the end of the list. - * - * @returns A new list consisting of the elements in the list on which - * it is called, followed in order by the elements of each argument. It - * does not recurse into nested iterable arguments - */ + concat(...lists: Iterable[]): ArrayList { const out = new ArrayList(this); for (const list of lists) { @@ -67,71 +47,26 @@ export class ArrayList implements List { } return out; } - /** - * Copies a section of the list identified by min and max to the same array at position index. - * - * Negative indices can be used for index, min and max to indicate an offset from the - * end of the list. For example, -2 refers to the second to last element of the list. - * - * Note that this method will not change the size of the list. If index is after min, - * the copied sequence will be trimmed to fit list.size - * - * @param index - Where to copy the sequence to - * @param min - Where to start copying elements from, inclusive. Defaults to 0 - * @param max - Where to end copying elements from, exclusive. Defaults to list.size - * - * @returns The list - */ + copyWithin(index: number, min?: number, max?: number): this { - index = wrap(index ?? 0, 0, this.size); - min = wrap(min ?? 0, 0, this.size); - max = wrap(max ?? this.size, 0, this.size); + index = cwrap(index ?? 0, 0, this.size); + min = cwrap(min ?? 0, 0, this.size); + max = cwrap(max ?? this.size, 0, this.size); this.array.copyWithin(index, min, max); return this; } - /** - * Returns the this object after filling the section identified by min and max with element. - * - * Negative indices can be used for min and max to indicate an offset from the - * end of the list. For example, -2 refers to the second to last element of the list. - * - * @param element — element to fill list section with - * @param min - Where to start filling the list, inclusive. Defaults to 0 - * @param end - Where to stop filling the list, exclusive. Defaults to list.size - * - * @returns The list on which this method was called - */ + fill(element: T, min?: number, max?: number): this { - min = wrap(min ?? 0, 0, this.size); - max = wrap(max ?? this.size, 0, this.size); + min = cwrap(min ?? 0, 0, this.size); + max = cwrap(max ?? this.size, 0, this.size); this.array.fill(element, min, max); return this; } - /** - * Return the element at the specified index. - * - * A negative index can be used for to indicate an offset from the - * end of the list. For example, -2 refers to the second to last element of the list. - * - * @param index - The index to retrieve - * - * @returns The element at the index, or `undefined` if index is invalid - */ + get(index: number): T | undefined { return index < 0 || index >= this.size ? undefined : this.array[index]; } - /** - * Update the element at the specified index. - * - * A negative index can be used to indicate an offset from the - * end of the list. For example, -2 refers to the second to last element of the list. - * - * @param index - The index to retrieve - * @param callback - A function that receives the previous element and returns - * the new element. The function is only called if the index is valid - * - * @returns The previous element at the index, or `undefined` if index is invalid - */ + getSet(index: number, callback: (element: T) => T): T | undefined { let value: T | undefined = undefined; if (index >= 0 && index < this.size) { @@ -140,51 +75,22 @@ export class ArrayList implements List { } return value; } - /** - * Retrieves and removes the end of the list - * - * @returns The element at the end of the list, or `undefined` if empty. - */ + pop(): T | undefined { return this.array.pop(); } - /** - * Inserts the specified element into the end of the list - * - * @param element - The element to be inserted - * - * @returns The new size of the list - */ + push(element: T): number { return this.array.push(element); } - /** - * Retrieves and removes the element at the given index. - * - * A negative index can be used to indicate an offset from the - * end of the list. For example, -2 refers to the second to last element of the list. - * - * @param index - The index to remove - * - * @returns The value at the index, or `undefined` if the index is invalid - */ + remove(index: number): T | undefined { return index < 0 || index >= this.size ? undefined : this.array.splice(index, 1)[0]; } - /** - * Reverses the elements in the list in place. - * - * Negative indices can be used for min and max to indicate an offset from the - * end of the list. For example, -2 refers to the second to last element of the list. - * - * @param min - The beginning index of the specified portion of the list, inclusive. Defaults to 0 - * @param max - The end index of the specified portion of the list, exclusive. Defaults to list.size - * - * @returns a reference to the same list - */ + reverse(min?: number, max?: number): this { - min = wrap(min ?? 0, 0, this.size); - max = wrap(max ?? this.size, 0, this.size) - 1; + min = cwrap(min ?? 0, 0, this.size); + max = cwrap(max ?? this.size, 0, this.size) - 1; while (min < max) { const temp = this.array[min]; this.array[min++] = this.array[max]; @@ -192,14 +98,7 @@ export class ArrayList implements List { } return this; } - /** - * Update the element at the specified index. - * - * @param index - The index to retrieve - * @param element - The new element to insert at index - * - * @returns The previous element in the index, or undefined if the index is invalid - */ + set(index: number, element: T): T | undefined { let prev: T | undefined = undefined; if (index >= 0 && index < this.size) { @@ -208,60 +107,21 @@ export class ArrayList implements List { } return prev; } - /** - * Retrieves and removes the first element in the list - * - * @returns The element at the front of the list or `undefined` if this list is empty. - */ + shift(): T | undefined { return this.array.shift(); } - /** - * The number of elements in this list - */ + get size(): number { return this.array.length; } - /** - * Returns a copy of a section of the list. - * - * Negative indices can be used for min and max to indicate an offset from the - * end of the list. For example, -2 refers to the second to last element of the list. - * - * @param min - The beginning index of the specified portion of the list, inclusive. Defaults to 0 - * @param max - The end index of the specified portion of the list, exclusive. Defaults to list.size - * - * @returns A new list with a copy of the indicated section of the original list - */ + slice(min?: number, max?: number): ArrayList { return new ArrayList(this.array.slice(min, max)); } - /** - * Removes elements from the list and optionally inserts new elements in their place. - * Returns any deleted elements. - * - * @param start - The index from which to start removing elements. Defaults to 0 - * - * If > size, start will be set to size. In this case, no element will be - * deleted but the method can still add elements to the end of the list. - * - * If < 0, start will indicate an offset from the end of the list. For example, - * -2 refers to the second to last element of the list. - * - * If < -size, start will be set to 0 - * @param count - The number of elements to remove. Defaults to size - start - * - * If >= size - start (that is, if it's >= than the number of elements from start - * until the end of the list), then all the elements from start until the end of - * the list will be removed. - * - * If <= 0, no elements are removed - * @param elements - The new elements to insert at start. Defaults to none - * - * @returns A new list of deleted elements - */ + splice(start?: number, count?: number, elements?: Iterable): List { - start = wrap(start ?? 0, 0, this.size); + start = cwrap(start ?? 0, 0, this.size); count = clamp(count ?? this.size, 0, this.size - start); const list = new ArrayList(this.array.splice(start, count)); for (const items of batch(10000, elements ?? [])) { @@ -270,6 +130,11 @@ export class ArrayList implements List { } return list; } + + sort(compareFn: CompareFn): this { + this.array.sort(compareFn); + return this; + } /** * Receive an iterator through the list. * @@ -280,48 +145,13 @@ export class ArrayList implements List { [Symbol.iterator](): Iterator { return this.array[Symbol.iterator](); } - /** - * Inserts the specified element into the front of the list - * - * @param element - The element to be inserted - * - * @returns The new size of the list - */ + unshift(element: T): number { return this.array.unshift(element); } - /** - * Update the elements of the list - * - * @param callback - A function called for each index. Returns the new element - * - * @returns The list on which this method was called - */ + update(callback: (element: T, index: number) => T): this; - /** - * Update the elements of the list - * - * Negative indices can be used to indicate an offset from the - * end of the list. For example, -2 refers to the second to last element of the list. - * - * @param min - Where to start filling the list, inclusive. Defaults to 0 - * @param callback - A function called for each index. Returns the new element - * - * @returns The list on which this method was called - */ update(min: number | undefined, callback: (element: T, index: number) => T): this; - /** - * Update the elements of the list - * - * Negative indices can be used for min and max to indicate an offset from the - * end of the list. For example, -2 refers to the second to last element of the list. - * - * @param min - Where to start filling the list, inclusive. Defaults to 0 - * @param max - Where to stop filling the list, exclusive. Defaults to list.size - * @param callback - A function called for each index. Returns the new element - * - * @returns The list on which this method was called - */ update( min: number | undefined, max: number | undefined, @@ -341,29 +171,17 @@ export class ArrayList implements List { max = undefined; } } - min = wrap((min as number) ?? 0, 0, this.size); - max = wrap((max as number) ?? this.size, 0, this.size); + min = cwrap((min as number) ?? 0, 0, this.size); + max = cwrap((max as number) ?? this.size, 0, this.size); while (min < max) { this.array[min] = callback(this.array[min], min); ++min; } return this; } - /** - * Receive an iterator through a section of the list. - * - * Negative indices can be used for min and max to indicate an offset from the - * end of the list. For example, -2 refers to the second to last element of the list. - * - * **Note:** Unexpected behavior can occur if the collection is modified during iteration. - * - * @param min - The beginning index of the specified portion of the list, inclusive. Defaults to 0 - * @param max - The end index of the specified portion of the list, exclusive. Defaults to list.size - * - * @returns An iterator through the indicated section of the list - */ + *view(min?: number, max?: number): Iterable { - min = wrap(min ?? 0, 0, this.size); + min = cwrap(min ?? 0, 0, this.size); let len: () => number; if (max == null) { diff --git a/src/list/doublyLinkedList.ts b/src/list/doublyLinkedList.ts index 310a416..b7e309e 100644 --- a/src/list/doublyLinkedList.ts +++ b/src/list/doublyLinkedList.ts @@ -1,5 +1,6 @@ +import { CompareFn } from '..'; import { List } from './list'; -import { clamp, wrap } from './utils'; +import { clamp, mergeSort, cwrap } from './utils'; /** * A doubly-linked node version of the {@link LinkedNode} interface. @@ -27,30 +28,25 @@ export interface DoublyLinkedNode { */ export class DoublyLinkedList implements List { /** - * @ignore - * The number of elements in this list + * The number of elements in the list */ protected length: number; /** - * @ignore - * The first node in the list + * The sentinel node at the fron of the list */ protected root: DoublyLinkedNode; - + /** + * Instantiate the list. + * + * @param elements - A set of elements to initialize the list with. + */ constructor(elements?: Iterable) { this.length = 0; this.root = {} as DoublyLinkedNode; this.root.prev = this.root.next = this.root; this._addAll(this.root, elements ?? []); } - /** - * Add the element at the specified index. - * - * @param index - The index to add into (0 <= index <= size) - * @param element - The element to add - * - * @returns The new size of the list - */ + add(index: number, value: T): number { if (index < 0 || index > this.length) { return this.length; @@ -61,37 +57,19 @@ export class DoublyLinkedList implements List { node.next!.prev = node; return ++this.length; } - /** - * Add elements at the specified index. - * - * @param index - The index to add into (0 <= index <= size) - * @param element - The elements to add - * - * @returns The new size of the list - */ + addAll(index: number, elements: Iterable): number { if (index >= 0 && index <= this.length) { this._addAll(this._get(index), elements); } return this.length; } - /** - * Removes all elements - */ + clear(): void { this.length = 0; this.root.prev = this.root.next = this.root; } - /** - * Combines the list with multiple iterables into a new list. - * Does not modify the existing list or inputs. - * - * @param lists — Additional iterables to add to the end of the list. - * - * @returns A new list consisting of the elements in the list on which - * it is called, followed in order by the elements of each argument. It - * does not recurse into nested iterable arguments - */ + concat(...lists: Iterable[]): DoublyLinkedList { const out = new DoublyLinkedList(this); for (const list of lists) { @@ -99,31 +77,17 @@ export class DoublyLinkedList implements List { } return out; } - /** - * Copies a section of the list identified by min and max to the same array at position index. - * - * Negative indices can be used for index, min and max to indicate an offset from the - * end of the list. For example, -2 refers to the second to last element of the list. - * - * Note that this method will not change the size of the list. If index is after min, - * the copied sequence will be trimmed to fit list.size - * - * @param index - Where to copy the sequence to - * @param min - Where to start copying elements from, inclusive. Defaults to 0 - * @param max - Where to end copying elements from, exclusive. Defaults to list.size - * - * @returns The list - */ + copyWithin(index: number, min?: number, max?: number): this { // Check if copying to the same section - index = wrap(index, 0, this.length); - min = wrap(min ?? 0, 0, this.length); + index = cwrap(index, 0, this.length); + min = cwrap(min ?? 0, 0, this.length); if (min === index) { return this; } // Check if the section to copy has no length - max = wrap(max ?? this.length, 0, this.length); + max = cwrap(max ?? this.length, 0, this.length); max = min + Math.min(max - min, this.length - index); if (min >= max) { return this; @@ -151,21 +115,10 @@ export class DoublyLinkedList implements List { } while (++min < max); return this; } - /** - * Returns the this object after filling the section identified by min and max with element. - * - * Negative indices can be used for min and max to indicate an offset from the - * end of the list. For example, -2 refers to the second to last element of the list. - * - * @param element — element to fill list section with - * @param min - Where to start filling the list, inclusive. Defaults to 0 - * @param end - Where to stop filling the list, exclusive. Defaults to list.size - * - * @returns The list on which this method was called - */ + fill(element: T, min?: number, max?: number): this { - min = wrap(min ?? 0, 0, this.length); - max = wrap(max ?? this.length, 0, this.length); + min = cwrap(min ?? 0, 0, this.length); + max = cwrap(max ?? this.length, 0, this.length); if (min < max) { let node = this._get(min); do { @@ -175,25 +128,11 @@ export class DoublyLinkedList implements List { } return this; } - /** - * Return the element at the specified index. - * - * @param index - The index to retrieve (0 <= index < size) - * - * @returns The element at the index, or `undefined` if index is invalid - */ + get(index: number): T | undefined { return index < 0 || index >= this.length ? undefined : this._get(index).value; } - /** - * Update the element at the specified index. - * - * @param index - The index to retrieve (0 <= index < size) - * @param callback - A function that receives the previous element and returns - * the new element. The function is only called if the index is valid - * - * @returns The previous element at the index, or `undefined` if index is invalid - */ + getSet(index: number, callback: (element: T) => T): T | undefined { if (index < 0 || index >= this.length) { return undefined; @@ -203,11 +142,7 @@ export class DoublyLinkedList implements List { node.value = callback(node.value); return value; } - /** - * Retrieves and removes the end of the list - * - * @returns The element at the end of the list, or `undefined` if empty. - */ + pop(): T | undefined { if (this.length < 1) { return undefined; @@ -218,26 +153,14 @@ export class DoublyLinkedList implements List { --this.length; return tail.value; } - /** - * Inserts the specified element into the end of the list - * - * @param element - The element to be inserted - * - * @returns `true` upon success, otherwise `false` - */ + push(value: T): number { const prev = this.root.prev!; const node = { next: this.root, prev, value }; prev.next = this.root.prev = node; return ++this.length; } - /** - * Retrieves and removes the element at the given index. - * - * @param index - The index to remove (0 <= index < size) - * - * @returns The value at the index, or `undefined` if the index is invalid - */ + remove(index: number): T | undefined { if (index < 0 || index >= this.length) { return undefined; @@ -248,20 +171,10 @@ export class DoublyLinkedList implements List { --this.length; return node.value; } - /** - * Reverses the elements in the list in place. - * - * Negative indices can be used for min and max to indicate an offset from the - * end of the list. For example, -2 refers to the second to last element of the list. - * - * @param min - The beginning index of the specified portion of the list, inclusive. Defaults to 0 - * @param max - The end index of the specified portion of the list, exclusive. Defaults to list.size - * - * @returns a reference to the same list - */ + reverse(min?: number, max?: number): this { - min = wrap(min ?? 0, 0, this.length); - max = wrap(max ?? this.length, 0, this.length); + min = cwrap(min ?? 0, 0, this.length); + max = cwrap(max ?? this.length, 0, this.length); if (max - min < 2) { return this; } @@ -280,14 +193,7 @@ export class DoublyLinkedList implements List { root.next!.prev = root; return this; } - /** - * Update the element at the specified index. - * - * @param index - The index to retrieve (0 <= index < size) - * @param element - The new element to insert at index - * - * @returns The previous element in the index, or undefined if the index is invalid - */ + set(index: number, element: T): T | undefined { if (index < 0 || index >= this.length) { return undefined; @@ -297,11 +203,7 @@ export class DoublyLinkedList implements List { node.value = element; return value; } - /** - * Retrieves and removes the first element in the list - * - * @returns The element at the front of the list or `undefined` if this list is empty. - */ + shift(): T | undefined { if (this.length < 1) { return undefined; @@ -312,52 +214,17 @@ export class DoublyLinkedList implements List { --this.length; return head.value; } - /** - * The number of elements in this list - */ + get size(): number { return this.length; } - /** - * Returns a copy of a section of the list. - * - * Negative indices can be used for min and max to indicate an offset from the - * end of the list. For example, -2 refers to the second to last element of the list. - * - * @param min - The beginning index of the specified portion of the list, inclusive. Defaults to 0 - * @param max - The end index of the specified portion of the list, exclusive. Defaults to list.size - * - * @returns A new list with a copy of the indicated section of the original list - */ + slice(min?: number, max?: number): DoublyLinkedList { return new DoublyLinkedList(this.view(min, max)); } - /** - * Removes elements from the list and optionally inserts new elements in their place. - * Returns any deleted elements. - * - * @param start - The index from which to start removing elements. Defaults to 0 - * - * If > size, start will be set to size. In this case, no element will be - * deleted but the method can still add elements to the end of the list. - * - * If < 0, start will indicate an offset from the end of the list. For example, - * -2 refers to the second to last element of the list. - * - * If < -size, start will be set to 0 - * @param count - The number of elements to remove. Defaults to size - start - * - * If >= size - start (that is, if it's >= than the number of elements from start - * until the end of the list), then all the elements from start until the end of - * the list will be removed. - * - * If <= 0, no elements are removed - * @param elements - The new elements to insert at start. Defaults to none - * - * @returns A new list of deleted elements - */ + splice(start?: number, count?: number, elements?: Iterable): List { - start = wrap(start ?? 0, 0, this.size); + start = cwrap(start ?? 0, 0, this.size); count = clamp(count ?? this.size, 0, this.size - start); // If not modifying the list @@ -381,6 +248,15 @@ export class DoublyLinkedList implements List { return list; } + + sort(compareFn: CompareFn): this { + if (this.length > 1) { + const [head, tail] = mergeSort(this.root.next!, this.length, true, compareFn); + this.root.next = head; + tail.next!.prev = tail; + } + return this; + } /** * Receive an iterator through the list. * @@ -393,51 +269,16 @@ export class DoublyLinkedList implements List { yield node.value; } } - /** - * Inserts the specified element into the front of the list - * - * @param element - The element to be inserted - * - * @returns `true` upon success, otherwise `false` - */ + unshift(value: T): number { const head = this.root.next!; const node = { next: head, prev: this.root, value }; this.root.next = head.prev = node; return ++this.length; } - /** - * Update the elements of the list - * - * @param callback - A function called for each index. Returns the new element - * - * @returns The list on which this method was called - */ + update(callback: (element: T, index: number) => T): this; - /** - * Update the elements of the list - * - * Negative indices can be used to indicate an offset from the - * end of the list. For example, -2 refers to the second to last element of the list. - * - * @param min - Where to start filling the list, inclusive. Defaults to 0 - * @param callback - A function called for each index. Returns the new element - * - * @returns The list on which this method was called - */ update(min: number | undefined, callback: (element: T, index: number) => T): this; - /** - * Update the elements of the list - * - * Negative indices can be used for min and max to indicate an offset from the - * end of the list. For example, -2 refers to the second to last element of the list. - * - * @param min - Where to start filling the list, inclusive. Defaults to 0 - * @param max - Where to stop filling the list, exclusive. Defaults to list.size - * @param callback - A function called for each index. Returns the new element - * - * @returns The list on which this method was called - */ update( min: number | undefined, max: number | undefined, @@ -457,8 +298,8 @@ export class DoublyLinkedList implements List { max = undefined; } } - min = wrap((min as number) ?? 0, 0, this.length); - max = wrap((max as number) ?? this.length, 0, this.length); + min = cwrap((min as number) ?? 0, 0, this.length); + max = cwrap((max as number) ?? this.length, 0, this.length); if (min < max) { let node = this._get(min); do { @@ -468,21 +309,9 @@ export class DoublyLinkedList implements List { } return this; } - /** - * Receive an iterator through a section of the list. - * - * Negative indices can be used for min and max to indicate an offset from the - * end of the list. For example, -2 refers to the second to last element of the list. - * - * **Note:** Unexpected behavior can occur if the collection is modified during iteration. - * - * @param min - The beginning index of the specified portion of the list, inclusive. Defaults to 0 - * @param max - The end index of the specified portion of the list, exclusive. Defaults to list.size - * - * @returns An iterator through the indicated section of the list - */ + *view(min?: number, max?: number): Iterable { - min = wrap(min ?? 0, 0, this.length); + min = cwrap(min ?? 0, 0, this.length); let len: () => number; if (max == null) { @@ -502,7 +331,6 @@ export class DoublyLinkedList implements List { } } /** - * @ignore * */ protected _addAll(next: DoublyLinkedNode, elements: Iterable): void { @@ -517,7 +345,6 @@ export class DoublyLinkedList implements List { next.prev = prev; } /** - * @ignore * A helper method to iterate and return the node at the given index. * * Depending on the index, the list will be traversed from beginning or end; whichever is closest to the specified index. diff --git a/src/list/linkedList.ts b/src/list/linkedList.ts index c7d5ad0..a855370 100644 --- a/src/list/linkedList.ts +++ b/src/list/linkedList.ts @@ -1,5 +1,6 @@ +import { CompareFn } from '..'; import { List } from './list'; -import { clamp, wrap } from './utils'; +import { clamp, mergeSort, cwrap } from './utils'; /** * A linked node interface. @@ -21,32 +22,29 @@ export interface LinkedNode { */ export class LinkedList implements List { /** - * @ignore + * The number of elements in the list. */ protected length: number; /** - * @ignore + * The sentinel node at the fron of the list. */ protected root: LinkedNode; /** - * @ignore + * The last node of the list. */ protected tail: LinkedNode; - + /** + * Instantiate the list. + * + * @param elements - A set of elements to initialize the list with. + */ constructor(elements?: Iterable) { this.length = 0; this.root = {} as LinkedNode; this.root.next = this.root; this.tail = this._addAll(this.root, elements ?? []); } - /** - * Add the element at the specified index. - * - * @param index - The index to add into (0 <= index <= size) - * @param element - The element to add - * - * @returns The new size of the list - */ + add(index: number, value: T): number { if (index >= 0 && index < this.length) { const prev = this._get(index - 1); @@ -57,14 +55,7 @@ export class LinkedList implements List { } return this.length; } - /** - * Add elements at the specified index. - * - * @param index - The index to add into (0 <= index <= size) - * @param element - The elements to add - * - * @returns The new size of the list - */ + addAll(index: number, elements: Iterable): number { if (index >= 0 && index < this.length) { this._addAll(this._get(index - 1), elements); @@ -73,23 +64,12 @@ export class LinkedList implements List { } return this.length; } - /** - * Removes all elements - */ + clear(): void { this.length = 0; this.tail = this.root.next = this.root; } - /** - * Combines the list with multiple iterables into a new list. - * Does not modify the existing list or inputs. - * - * @param lists — Additional iterables to add to the end of the list. - * - * @returns A new list consisting of the elements in the list on which - * it is called, followed in order by the elements of each argument. It - * does not recurse into nested iterable arguments - */ + concat(...lists: Iterable[]): LinkedList { const out = new LinkedList(this); for (const list of lists) { @@ -97,31 +77,17 @@ export class LinkedList implements List { } return out; } - /** - * Copies a section of the list identified by min and max to the same array at position index. - * - * Negative indices can be used for index, min and max to indicate an offset from the - * end of the list. For example, -2 refers to the second to last element of the list. - * - * Note that this method will not change the size of the list. If index is after min, - * the copied sequence will be trimmed to fit list.size - * - * @param index - Where to copy the sequence to - * @param min - Where to start copying elements from, inclusive. Defaults to 0 - * @param max - Where to end copying elements from, exclusive. Defaults to list.size - * - * @returns The list - */ + copyWithin(index: number, min?: number, max?: number): this { // Check if copying to itself - index = wrap(index, 0, this.length); - min = wrap(min ?? 0, 0, this.length); + index = cwrap(index, 0, this.length); + min = cwrap(min ?? 0, 0, this.length); if (min === index) { return this; } // Check if the section to copy has no length - max = wrap(max ?? this.length, 0, this.length); + max = cwrap(max ?? this.length, 0, this.length); max = min + Math.min(max - min, this.length - index); if (min >= max) { return this; @@ -154,21 +120,10 @@ export class LinkedList implements List { nodeD.next = temp; return this; } - /** - * Returns the this object after filling the section identified by min and max with element. - * - * Negative indices can be used for min and max to indicate an offset from the - * end of the list. For example, -2 refers to the second to last element of the list. - * - * @param element — element to fill list section with - * @param min - Where to start filling the list, inclusive. Defaults to 0 - * @param end - Where to stop filling the list, exclusive. Defaults to list.size - * - * @returns The list on which this method was called - */ + fill(element: T, min?: number, max?: number): this { - min = wrap(min ?? 0, 0, this.length); - max = wrap(max ?? this.length, 0, this.length); + min = cwrap(min ?? 0, 0, this.length); + max = cwrap(max ?? this.length, 0, this.length); if (min < max) { let node = this._get(min); do { @@ -178,28 +133,14 @@ export class LinkedList implements List { } return this; } - /** - * Return the element at the specified index. - * - * @param index - The index to retrieve (0 <= index < size) - * - * @returns The element at the index, or `undefined` if index is invalid - */ + get(index: number): T | undefined { if (index < 0 || index >= this.length) { return undefined; } return index < this.length - 1 ? this._get(index).value : this.tail.value; } - /** - * Update the element at the specified index. - * - * @param index - The index to retrieve (0 <= index < size) - * @param callback - A function that receives the previous element and returns - * the new element. The function is only called if the index is valid - * - * @returns The previous element at the index, or `undefined` if index is invalid - */ + getSet(index: number, callback: (element: T) => T): T | undefined { if (index < 0 || index >= this.length) { return undefined; @@ -209,11 +150,7 @@ export class LinkedList implements List { node.value = callback(node.value); return value; } - /** - * Retrieves and removes the end of the list - * - * @returns The value at the end of the list, or `undefined` if empty. - */ + pop(): T | undefined { if (this.length < 1) { return undefined; @@ -224,26 +161,14 @@ export class LinkedList implements List { --this.length; return value; } - /** - * Inserts the specified value into the end of the list - * - * @param element - The element to be inserted - * - * @returns `true` upon success, otherwise `false` - */ + push(value: T): number { const tail: LinkedNode = { next: this.root, value }; this.tail.next = tail; this.tail = tail; return ++this.length; } - /** - * Retrieves and removes the element at the given index. - * - * @param index - The index to remove (0 <= index < size) - * - * @returns The value at the index, or `undefined` if the index is invalid - */ + remove(index: number): T | undefined { if (index < 0 || index >= this.length) { return undefined; @@ -256,20 +181,10 @@ export class LinkedList implements List { } return node.value; } - /** - * Reverses the elements in the list in place. - * - * Negative indices can be used for min and max to indicate an offset from the - * end of the list. For example, -2 refers to the second to last element of the list. - * - * @param min - The beginning index of the specified portion of the list, inclusive. Defaults to 0 - * @param max - The end index of the specified portion of the list, exclusive. Defaults to list.size - * - * @returns a reference to the same list - */ + reverse(min?: number, max?: number): this { - min = wrap(min ?? 0, 0, this.length); - max = wrap(max ?? this.length, 0, this.length); + min = cwrap(min ?? 0, 0, this.length); + max = cwrap(max ?? this.length, 0, this.length); if (max - min < 2) { return this; } @@ -288,14 +203,7 @@ export class LinkedList implements List { tail.next = node; return this; } - /** - * Update the element at the specified index. - * - * @param index - The index to retrieve (0 <= index < size) - * @param element - The new element to insert at index - * - * @returns The previous element in the index, or undefined if the index is invalid - */ + set(index: number, element: T): T | undefined { if (index < 0 || index >= this.length) { return undefined; @@ -305,60 +213,21 @@ export class LinkedList implements List { node.value = element; return value; } - /** - * Retrieves and removes the first element in the list - * - * @returns The value at the front of the list or `undefined` if this list is empty. - */ + shift(): T | undefined { return this.remove(0); } - /** - * The number of elements in this list - */ + get size(): number { return this.length; } - /** - * Returns a copy of a section of the list. - * - * Negative indices can be used for min and max to indicate an offset from the - * end of the list. For example, -2 refers to the second to last element of the list. - * - * @param min - The beginning index of the specified portion of the list, inclusive. Defaults to 0 - * @param max - The end index of the specified portion of the list, exclusive. Defaults to list.size - * - * @returns A new list with a copy of the indicated section of the original list - */ + slice(min?: number, max?: number): LinkedList { return new LinkedList(this.view(min, max)); } - /** - * Removes elements from the list and optionally inserts new elements in their place. - * Returns any deleted elements. - * - * @param start - The index from which to start removing elements. Defaults to 0 - * - * If > size, start will be set to size. In this case, no element will be - * deleted but the method can still add elements to the end of the list. - * - * If < 0, start will indicate an offset from the end of the list. For example, - * -2 refers to the second to last element of the list. - * - * If < -size, start will be set to 0 - * @param count - The number of elements to remove. Defaults to size - start - * - * If >= size - start (that is, if it's >= than the number of elements from start - * until the end of the list), then all the elements from start until the end of - * the list will be removed. - * - * If <= 0, no elements are removed - * @param elements - The new elements to insert at start. Defaults to none - * - * @returns A new list of deleted elements - */ + splice(start?: number, count?: number, elements?: Iterable): List { - start = wrap(start ?? 0, 0, this.size); + start = cwrap(start ?? 0, 0, this.size); count = clamp(count ?? this.size, 0, this.size - start); // If not modifying the list @@ -383,6 +252,15 @@ export class LinkedList implements List { return deleted; } + + sort(compareFn: CompareFn): this { + if (this.length > 1) { + const [head, tail] = mergeSort(this.root.next!, this.length, false, compareFn); + this.root.next = head; + this.tail = tail; + } + return this; + } /** * Receive an iterator through the list. * @@ -395,48 +273,13 @@ export class LinkedList implements List { yield node.value; } } - /** - * Inserts the specified value into the front of the list - * - * @param element - The element to be inserted - * - * @returns `true` upon success, otherwise `false` - */ + unshift(value: T): number { return this.add(0, value); } - /** - * Update the elements of the list - * - * @param callback - A function called for each index. Returns the new element - * - * @returns The list on which this method was called - */ + update(callback: (element: T, index: number) => T): this; - /** - * Update the elements of the list - * - * Negative indices can be used to indicate an offset from the - * end of the list. For example, -2 refers to the second to last element of the list. - * - * @param min - Where to start filling the list, inclusive. Defaults to 0 - * @param callback - A function called for each index. Returns the new element - * - * @returns The list on which this method was called - */ update(min: number | undefined, callback: (element: T, index: number) => T): this; - /** - * Update the elements of the list - * - * Negative indices can be used for min and max to indicate an offset from the - * end of the list. For example, -2 refers to the second to last element of the list. - * - * @param min - Where to start filling the list, inclusive. Defaults to 0 - * @param max - Where to stop filling the list, exclusive. Defaults to list.size - * @param callback - A function called for each index. Returns the new element - * - * @returns The list on which this method was called - */ update( min: number | undefined, max: number | undefined, @@ -456,8 +299,8 @@ export class LinkedList implements List { max = undefined; } } - min = wrap((min as number) ?? 0, 0, this.length); - max = wrap((max as number) ?? this.length, 0, this.length); + min = cwrap((min as number) ?? 0, 0, this.length); + max = cwrap((max as number) ?? this.length, 0, this.length); if (min < max) { let node = this._get(min); do { @@ -467,21 +310,9 @@ export class LinkedList implements List { } return this; } - /** - * Receive an iterator through a section of the list. - * - * Negative indices can be used for min and max to indicate an offset from the - * end of the list. For example, -2 refers to the second to last element of the list. - * - * **Note:** Unexpected behavior can occur if the collection is modified during iteration. - * - * @param min - The beginning index of the specified portion of the list, inclusive. Defaults to 0 - * @param max - The end index of the specified portion of the list, exclusive. Defaults to list.size - * - * @returns An iterator through the indicated section of the list - */ + *view(min?: number, max?: number): Iterable { - min = wrap(min ?? 0, 0, this.length); + min = cwrap(min ?? 0, 0, this.length); let len: () => number; if (max == null) { @@ -500,6 +331,7 @@ export class LinkedList implements List { } while (++min < len() && node !== this.root); } } + protected _addAll(prev: LinkedNode, elements: Iterable): LinkedNode { const next = prev.next!; for (const value of elements) { @@ -512,7 +344,6 @@ export class LinkedList implements List { return prev; } /** - * @ignore * Copy values from 'from' to 'to'. * * @param from - The initial node to copy from @@ -528,7 +359,6 @@ export class LinkedList implements List { return to; } /** - * @ignore * Get the node at the given index. * * @param index - The index to retrieve diff --git a/src/list/list.ts b/src/list/list.ts index ac282dc..2ad0165 100644 --- a/src/list/list.ts +++ b/src/list/list.ts @@ -1,3 +1,5 @@ +import { Sortable } from '..'; + /** * An ordered collection (also known as a sequence). A list allows exactly stating * where an element is inserted. Elements can be accessed by their integer index (position in the list) @@ -7,6 +9,7 @@ * - Iterate a subset of the list: {@link view} * * #### Get + * - Get the size of the list: {@link size} * - Get the element at a given index: {@link get} * - Get the elements in a given range: {@link slice} * @@ -15,6 +18,7 @@ * - Add 1 at the end: {@link push} * - Add 1 at a given index: {@link add} * - Add 1+ at a given index: {@link addAll} + * - Add 1+ into a new list: {@link concat} * * #### Set * - Set 1 index: {@link set} @@ -22,14 +26,17 @@ * - Set a range to 1 element: {@link fill} * - Set a range to a copy of another range within the list: {@link copyWithin} * - Set a range: {@link update} + * - Sort the list: {@link sort} + * - Reverse the list {@link reverse} * * #### Remove * - Remove 1 from the start: {@link shift} * - Remove 1 from the end: {@link pop} * - Remove 1 from a given index: {@link remove} * - Remove a range (and add new elements): {@link splice} + * - Remove all elements: {@link clear} */ -export interface List extends Iterable { +export interface List extends Iterable, Sortable { /** * Add the element at the specified index. * diff --git a/src/list/utils.ts b/src/list/utils.ts index a3a3e30..3ab5f70 100644 --- a/src/list/utils.ts +++ b/src/list/utils.ts @@ -1,11 +1,25 @@ +import { CompareFn } from '..'; +import { DoublyLinkedNode } from './doublyLinkedList'; +import { LinkedNode } from './linkedList'; + /** - * @ignore + * Groups an iterable into batches of a given size. + * + * @param size - The maximum batch size + * @param iterable - The iterable to batch + * + * @returns An iterable of batches + * + * @internal */ -export function* batch(size: number, elements: Iterable): Generator { +export function* batch( + size: number, + iterable: Iterable, +): Generator { let array: T[] = []; - for (const element of elements) { - if (array.push(element) >= size) { - yield array; + for (const value of iterable) { + if (array.push(value) >= size) { + size = (yield array) ?? size; array = []; } } @@ -14,14 +28,158 @@ export function* batch(size: number, elements: Iterable): Generator { } } /** - * @ignore + * Limits a number to be within a given range. + * + * f(x, min, max) = y, where min <= y <= max + * + * @param num - The number to clamp + * @param min - The minimum result value, inclusive + * @param max - The maximum result value, inclusive + * + * @returns The clamped number + * + * @internal */ export function clamp(num: number, min: number, max: number): number { return Math.min(max, Math.max(min, num)); } /** - * @ignore + * Wraps and then clamps a number within a given range. + * + * @param num - The number to wrap and then clamp + * @param min - The minimum result value, inclusive + * @param max - The wrap pivot and maximum result value, inclusive + * + * @returns The crwapped number + * + * @internal */ -export function wrap(num: number, min: number, max: number): number { - return clamp(num < 0 ? max + num : num, min, max); +export function cwrap(num: number, min: number, max: number): number { + return clamp(wrap(num, max), min, max); +} +/** + * Sorts a list in place. + * + * Works on complete lists as well as sublists and circular lists: + * - Linked lists will keep the link to the next node beyond the sorted section + * - Doubly linked lists will keep links to the prev and next nodes outside the sorted section + * + * @param node - The head of the list + * @param len - The length of the list beginning from node + * @param isDoubly - Whether node is a doubly linked node + * @param compareFn - A function used to determine the order of elements. + * + * It is expected to return: + * - A negative value if first argument < second argument + * - Zero if first argument == second argument + * - A positive value if first argument > second argument + * + * @returns The new head and tail of the sorted list + * + * @internal + */ +export function mergeSort>( + node: Node, + len: number, + isDoubly: boolean, + compareFn: CompareFn, +): [Node, Node] { + // Base case + if (len < 2) { + return [node, node]; + } + + // Split the list into two halves and sort them + len = len / 2; + const lens: [number, number] = [Math.ceil(len), Math.floor(len)]; + const heads = mergeSort(node, lens[0], isDoubly, compareFn); + const tails = mergeSort(heads[1].next as Node, lens[1], isDoubly, compareFn); + + // Group the heads and tails together + node = heads[1]; + heads[1] = tails[0]; + tails[0] = node; + tails[0].next = tails[1].next; + + // Merge the sorted halves + const prev = (heads[0] as DoublyLinkedNode).prev; + node = mergeSorted(heads, lens, isDoubly, compareFn); + isDoubly && ((node as DoublyLinkedNode).prev = prev); + + // Return the head and tail + return [node, tails[+(lens[0] < 1)]]; +} +/** + * Merges two sorted lists. + * + * @param nodes - The heads of the lists + * @param lens - The lengths of the lists + * @param isDoubly - Whether the lists are a doubly linked + * @param compareFn - A function used to determine the order of elements. + * + * It is expected to return: + * - A negative value if first argument < second argument + * - Zero if first argument == second argument + * - A positive value if first argument > second argument + * + * @returns The new head of the sorted list + * + * @internal + */ +export function mergeSorted>( + heads: [Node, Node], + lens: [number, number], + isDoubly: boolean, + compareFn: CompareFn, +): Node { + const root = {} as Node; + + let node = root; + do { + const index = +(compareFn(heads[0].value, heads[1].value) > 0); + node.next = heads[index]; + isDoubly && ((node.next as DoublyLinkedNode).prev = node); + node = node.next as Node; + heads[index] = node.next as Node; + --lens[index]; + } while (lens[0] > 0 && lens[1] > 0); + + // Add any remaining nodes + node.next = heads[+(lens[0] < 1)]; + isDoubly && node.next && ((node.next as DoublyLinkedNode).prev = node); + return root.next as Node; +} +/** + * Moves a given number of spaces forward in a list + * + * @param head - The head of the list + * @param len - The number of spaces to move + * + * @returns - The node len spaces ahead from head + * + * @internal + */ +export function next>(head: Node, len: number): Node { + while (len-- > 0) { + head = head.next as Node; + } + return head; +} +/** + * Wraps a number around a pivot + * + * f(x, min, pivot) = { + * x, where x >= 0 + * pivot + x, where x < 0 + * } + * + * @param num - The number to wrap + * @param pivot - The number to pivot on + * + * @returns - The wrapped number + * + * @internal + */ +export function wrap(num: number, pivot: number): number { + return num < 0 ? pivot + num : num; } diff --git a/src/queue/arrayQueue.ts b/src/queue/arrayQueue.ts index a22d52c..569e979 100644 --- a/src/queue/arrayQueue.ts +++ b/src/queue/arrayQueue.ts @@ -5,46 +5,34 @@ import { Queue } from './queue'; */ export class ArrayQueue implements Queue { /** - * @ignore + * The array containing every element. */ protected array: T[]; - + /** + * Instantiate the queue. + * + * @param elements - A set of elements to initialize the queue with. + */ constructor(elements?: Iterable) { this.array = elements ? Array.from(elements) : []; } - /** - * Removes all elements from this queue - */ + clear(): void { this.array.length = 0; } - /** - * Retrieves and removes the head of this queue - * - * @returns The element at the head of the queue or `undefined` if this queue is empty. - */ + dequeue(): T | undefined { return this.size < 1 ? undefined : this.array.shift(); } - /** - * Inserts the specified element into this queue - * - * @param element - The element to be inserted - */ + enqueue(element: T): number { return this.array.push(element); } - /** - * Retrieves, but does not remove, the head of this queue - * - * @returns The value at the head of the queue or `undefined` if this queue is empty. - */ + peek(): T | undefined { return this.size < 1 ? undefined : this.array[0]; } - /** - * The number of elements in this queue - */ + get size(): number { return this.array.length; } diff --git a/src/queue/linkedQueue.ts b/src/queue/linkedQueue.ts index 44dec8b..899a8ef 100644 --- a/src/queue/linkedQueue.ts +++ b/src/queue/linkedQueue.ts @@ -6,46 +6,34 @@ import { Queue } from './queue'; */ export class LinkedQueue implements Queue { /** - * @ignore + * The list containing every element. */ protected list: List; - + /** + * Instantiate the queue. + * + * @param elements - A set of elements to initialize the queue with. + */ constructor(elements?: Iterable) { this.list = new LinkedList(elements); } - /** - * Removes all elements from this queue - */ + clear(): void { this.list.clear(); } - /** - * Retrieves and removes the head of this queue - * - * @returns The element at the head of the queue or `undefined` if this queue is empty. - */ + dequeue(): T | undefined { return this.list.shift(); } - /** - * Inserts the specified element into this queue - * - * @param element - The element to be inserted - */ + enqueue(element: T): number { return this.list.push(element); } - /** - * Retrieves, but does not remove, the head of this queue - * - * @returns The element at the head of the queue or `undefined` if this queue is empty. - */ + peek(): T | undefined { return this.list.get(0); } - /** - * The number of elements in this queue - */ + get size(): number { return this.list.size; } diff --git a/src/stack/arrayStack.ts b/src/stack/arrayStack.ts index 4d00f07..1b48f1f 100644 --- a/src/stack/arrayStack.ts +++ b/src/stack/arrayStack.ts @@ -5,48 +5,34 @@ import { Stack } from './stack'; */ export class ArrayStack implements Stack { /** - * @ignore + * The array containing every element. */ protected array: T[]; - + /** + * Instantiate the stack. + * + * @param elements - A set of elements to initialize the stack with. + */ constructor(elements?: Iterable) { this.array = elements ? Array.from(elements) : []; } - /** - * Removes all elements from the stack - */ + clear(): void { this.array.length = 0; } - /** - * Retrieves, but does not remove, the top of the stack - * - * @returns The element at the top of the stack or `undefined` if empty. - */ + peek(): T | undefined { return this.array[this.array.length - 1]; } - /** - * Retrieves and removes the top of the stack - * - * @returns The element at the top of the stack or `undefined` if empty. - */ + pop(): T | undefined { return this.array.pop(); } - /** - * Inserts a element into the stack - * - * @param element - The element to be inserted - * - * @returns The new size of the stack - */ + push(element: T): number { return this.array.push(element); } - /** - * The number of elements in the stack - */ + get size(): number { return this.array.length; } diff --git a/src/stack/linkedStack.ts b/src/stack/linkedStack.ts index e627e0d..e9c327f 100644 --- a/src/stack/linkedStack.ts +++ b/src/stack/linkedStack.ts @@ -6,51 +6,37 @@ import { Stack } from './stack'; */ export class LinkedStack implements Stack { /** - * @ignore + * The list containing every element. */ protected list: List; - + /** + * Instantiate the stack. + * + * @param elements - A set of elements to initialize the stack with. + */ constructor(elements?: Iterable) { this.list = new LinkedList(); for (const element of elements || []) { this.push(element); } } - /** - * Removes all elements from the stack - */ + clear(): void { this.list.clear(); } - /** - * Retrieves, but does not remove, the top of the stack - * - * @returns The element at the top of the stack or `undefined` if empty. - */ + peek(): T | undefined { return this.list.get(0); } - /** - * Retrieves and removes the top of the stack - * - * @returns The element at the top of the stack or `undefined` if empty. - */ + pop(): T | undefined { return this.list.shift(); } - /** - * Inserts a element into the stack - * - * @param element - The element to be inserted - * - * @returns The new size of the stack - */ + push(element: T): number { return this.list.unshift(element); } - /** - * The number of elements in the stack - */ + get size(): number { return this.list.size; } diff --git a/src/tree/index.ts b/src/tree/index.ts new file mode 100644 index 0000000..6d1626a --- /dev/null +++ b/src/tree/index.ts @@ -0,0 +1,17 @@ +/** + * + */ +export interface BinaryTreeNode { + /** + * + */ + value: T; + /** + * + */ + left?: BinaryTreeNode; + /** + * + */ + right?: BinaryTreeNode; +} diff --git a/src/tree/utils.ts b/src/tree/utils.ts new file mode 100644 index 0000000..3f91e2a --- /dev/null +++ b/src/tree/utils.ts @@ -0,0 +1,133 @@ +import { LinkedStack } from 'src/stack'; +import { BinaryTreeNode } from '.'; + +/** + * + * @param node + * + * @returns + * + * @internal + */ +export function clone(node: BinaryTreeNode | undefined): BinaryTreeNode | undefined { + if (node == null) { + return undefined; + } + const out: BinaryTreeNode = Object.assign({}, node); + const stack = new LinkedStack>([out]); + do { + node = stack.pop()!; + if (node.left) { + stack.push((node.left = Object.assign({}, node.left))); + } else if (node.right) { + stack.push((node.right = Object.assign({}, node.right))); + } + } while (stack.size > 0); + return out; +} +/** + * + * @param elements + * + * @returns + * + * @internal + */ +export function toBinaryTree(elements: T[] | undefined): BinaryTreeNode | undefined { + if (elements == null || elements.length < 1) { + return undefined; + } + const n = elements.length; + const nodes = new Array(n); + nodes[0] = { value: elements[0] }; + for (let i = 1; i < n; ++i) { + const par = nodes[(i - 1) >>> 1]; + const node = { value: elements[i] }; + nodes[i] = node; + if (i & 1) { + par.left = node; + } else { + par.right = node; + } + } + return nodes[0]; +} +/** + * + * @param node + * + * @returns + * + * @internal + */ +export function* inOrderTraverse( + node: BinaryTreeNode | undefined, +): Iterable> { + const stack = new LinkedStack>(); + + while (node != null) { + stack.push(node); + node = node.left; + } + + while (stack.size > 0) { + node = stack.pop()!; + yield node; + node = node.right; + while (node != null) { + stack.push(node); + node = node.left; + } + } +} +/** + * + * @param node + * + * @returns + * + * @internal + */ +export function* postOrderTraverse( + node: BinaryTreeNode | undefined, +): Iterable> { + interface Meta { + seen: boolean; + node?: BinaryTreeNode; + } + const stack = new LinkedStack([{ seen: false, node }]); + do { + const meta = stack.pop()!; + if (meta.node != null) { + if (meta.seen) { + yield meta.node; + } else { + meta.seen = true; + stack.push(meta); + stack.push({ seen: false, node: meta.node.right }); + stack.push({ seen: false, node: meta.node.left }); + } + } + } while (stack.size > 0); +} +/** + * + * @param node + * + * @returns + * + * @internal + */ +export function* preOrderTraverse( + node: BinaryTreeNode | undefined, +): Iterable> { + const stack = new LinkedStack | undefined>([node]); + do { + node = stack.pop()!; + if (node != null) { + yield node; + stack.push(node.right); + stack.push(node.left); + } + } while (stack.size > 0); +} diff --git a/test/heap/binaryHeap.ts b/test/heap/binaryHeap.ts index 2d8f71b..b7fd306 100644 --- a/test/heap/binaryHeap.ts +++ b/test/heap/binaryHeap.ts @@ -1,8 +1,9 @@ import { expect } from 'chai'; import { randomFill, randomInt } from 'crypto'; +import { SkewHeap } from 'src/heap'; import { BinaryHeap } from 'src/heap/binaryHeap'; -describe.only('BinaryHeap unit tests', function () { +describe('BinaryHeap unit tests', function () { const compareFn = (a: number, b: number) => a - b; let empty: BinaryHeap; let filled: BinaryHeap; @@ -19,7 +20,37 @@ describe.only('BinaryHeap unit tests', function () { filled = new BinaryHeap(compareFn, values); }); - describe('#clear()', function() { + describe('#addAll()', function () { + it('Should work when empty', function () { + expect(empty.addAll([3, 2, 1])).to.equal(3); + expect(empty.peek()).to.equal(1); + expect(empty.size).to.equal(3); + }); + it('Should work when not empty', function () { + expect(filled.addAll([-1, -2, -3])).to.equal(values.length + 3); + expect(filled.peek()).to.equal(-3); + expect(filled.size).to.equal(values.length + 3); + }); + it('Should not break heap', function () { + for (let i = 0; i <= values.length; ++i) { + const arr1 = Array.from(values.slice(0, i)); + for (let j = 0; j <= updatedValues.length; ++j) { + const arr2 = Array.from(updatedValues.slice(0, j)); + const heap = new BinaryHeap(compareFn, arr1); + expect(heap.size).to.equal(arr1.length); + expect(heap.addAll(arr2)).to.equal(i + j); + const sorted = arr1.concat(arr2); + sorted.sort((a, b) => compareFn(b, a)); + expect(heap.size).to.equal(sorted.length); + for (let k = i + j - 1; k >= 0; --k) { + expect(heap.pop()).to.equal(sorted[k]); + expect(heap.size).to.equal(k); + } + } + } + }); + }); + describe('#clear()', function () { it('Should clear when empty', function () { empty.clear(); expect(empty.size).to.equal(0); @@ -45,7 +76,7 @@ describe.only('BinaryHeap unit tests', function () { expect(Array.from(empty.dump())).to.eql([]); }); }); - describe('#contains()', function() { + describe('#contains()', function () { it('Should return false when empty', function () { expect(empty.contains(values[0])).to.equal(false); }); @@ -53,12 +84,12 @@ describe.only('BinaryHeap unit tests', function () { expect(filled.contains(-99)).to.equal(false); }); it('Should return true if found', function () { - for(let i = 0; i < values.length; ++i) { + for (let i = 0; i < values.length; ++i) { expect(filled.contains(values[i])).to.equal(true); } }); }); - describe('#delete()', function() { + describe('#delete()', function () { it('Should return false when empty', function () { expect(empty.delete(1)).to.equal(false); expect(empty.peek()).to.equal(undefined); @@ -69,18 +100,18 @@ describe.only('BinaryHeap unit tests', function () { expect(filled.size).to.equal(values.length); }); it('Should return true if found', function () { - for(let i = 0; i < values.length; ++i) { + for (let i = 0; i < values.length; ++i) { expect(filled.delete(values[i])).to.equal(true); } }); it('Should decrease size', function () { - for(let i = values.length - 1; i >= 0; --i) { + for (let i = values.length - 1; i >= 0; --i) { expect(filled.delete(values[i])).to.equal(true); expect(filled.size).to.equal(i); } }); it('Should update heap', function () { - empty.merge([20, 15, 10, 5]); + empty.addAll([20, 15, 10, 5]); empty.delete(10); expect(empty.peek()).to.equal(5); expect(empty.size).to.equal(3); @@ -102,13 +133,13 @@ describe.only('BinaryHeap unit tests', function () { expect(heap.delete(val)).to.equal(true); expect(heap.size).to.equal(vals.length); const sorted = Array.from(vals).sort((a, b) => compareFn(b, a)); - while(heap.size > 0) { + while (heap.size > 0) { expect(heap.pop()).to.equal(sorted.pop()); } } }); }); - describe('#dump()', function() { + describe('#dump()', function () { it('Should work when empty', function () { expect(Array.from(empty.dump())).to.eql([]); }); @@ -122,25 +153,67 @@ describe.only('BinaryHeap unit tests', function () { expect(actual).to.eql(expected); }); }); - describe('#merge()', function() { + describe('#merge()', function () { it('Should work when empty', function () { - expect(empty.merge([3,2,1])).to.equal(3); - expect(empty.peek()).to.equal(1); - expect(empty.size).to.equal(3); + expect(empty.merge(filled)).to.equal(empty); + expect(empty.peek()).to.equal(filled.peek()); + expect(empty.size).to.equal(filled.size); }); it('Should work when not empty', function () { - expect(filled.merge([-1, -2, -3])).to.equal(values.length + 3); - expect(filled.peek()).to.equal(-3); - expect(filled.size).to.equal(values.length + 3); + const heap = new BinaryHeap(compareFn, filled.dump()); + expect(filled.merge(heap)).to.equal(filled); + expect(filled.peek()).to.equal(filled.peek()); + expect(filled.size).to.equal(2 * heap.size); }); - it('Should not break heap', function() { + it('Should work with BinaryHeap', function () { for (let i = 0; i <= values.length; ++i) { const arr1 = Array.from(values.slice(0, i)); for (let j = 0; j <= updatedValues.length; ++j) { const arr2 = Array.from(updatedValues.slice(0, j)); const heap = new BinaryHeap(compareFn, arr1); expect(heap.size).to.equal(arr1.length); - expect(heap.merge(arr2)).to.equal(i + j); + expect(heap.merge(new BinaryHeap(compareFn, arr2))).to.equal(heap); + expect(heap.size).to.equal(i + j); + const sorted = arr1.concat(arr2); + sorted.sort((a, b) => compareFn(b, a)); + expect(heap.size).to.equal(sorted.length); + for (let k = i + j - 1; k >= 0; --k) { + expect(heap.pop()).to.equal(sorted[k]); + expect(heap.size).to.equal(k); + } + } + } + }); + it('Should work with SkewHeap', function () { + for (let i = 0; i <= values.length; ++i) { + const arr1 = Array.from(values.slice(0, i)); + for (let j = 0; j <= updatedValues.length; ++j) { + const arr2 = Array.from(updatedValues.slice(0, j)); + const heap = new SkewHeap(compareFn, arr1); + expect(heap.size).to.equal(arr1.length); + expect(heap.merge(new SkewHeap(compareFn, arr2))).to.equal(heap); + expect(heap.size).to.equal(i + j); + const sorted = arr1.concat(arr2); + sorted.sort((a, b) => compareFn(b, a)); + expect(heap.size).to.equal(sorted.length); + for (let k = i + j - 1; k >= 0; --k) { + expect(heap.pop()).to.equal(sorted[k]); + expect(heap.size).to.equal(k); + } + } + } + }); + it('Should work with generic heap', async function () { + this.timeout(60000) + for (let i = 0; i <= values.length; ++i) { + const arr1 = Array.from(values.slice(0, i)); + for (let j = 0; j <= updatedValues.length; ++j) { + const arr2 = Array.from(updatedValues.slice(0, j)); + const heap = new BinaryHeap(compareFn, arr1); + expect(heap.size).to.equal(arr1.length); + const heap2 = { size: arr2.length, dump: () => arr2 } as any; + expect(heap.merge(heap2)).to.equal(heap); + expect(heap.size).to.equal(i + j); const sorted = arr1.concat(arr2); sorted.sort((a, b) => compareFn(b, a)); expect(heap.size).to.equal(sorted.length); @@ -152,7 +225,7 @@ describe.only('BinaryHeap unit tests', function () { } }); }); - describe('#peek()', function() { + describe('#peek()', function () { it('Should return `undefined` when empty', function () { expect(empty.peek()).to.equal(undefined); expect(empty.peek()).to.equal(undefined); @@ -168,7 +241,7 @@ describe.only('BinaryHeap unit tests', function () { }); it('Should return the smallest values as heap grows', function () { for (let i = 0; i < values.length; ++i) { - const vals = Array.from(values.slice(0, i+1)).sort(compareFn); + const vals = Array.from(values.slice(0, i + 1)).sort(compareFn); empty.push(values[i]); expect(empty.peek()).to.equal(vals[0]); } @@ -176,13 +249,13 @@ describe.only('BinaryHeap unit tests', function () { it('Should return the smallest values as heap shrinks', function () { const vals = Array.from(values).sort((a, b) => compareFn(b, a)); for (let i = values.length; i > 0; --i) { - expect(filled.peek()).to.equal(vals[i- 1]); + expect(filled.peek()).to.equal(vals[i - 1]); filled.pop(); vals.pop(); } }); }); - describe('#pop()', function() { + describe('#pop()', function () { it('Should work when empty', function () { expect(empty.pop()).to.equal(undefined); expect(empty.size).to.equal(0); @@ -214,7 +287,7 @@ describe.only('BinaryHeap unit tests', function () { } }); }); - describe('#push()', function() { + describe('#push()', function () { it('Should work when empty', function () { expect(empty.push(1)).to.equal(1); expect(empty.peek()).to.equal(1); @@ -236,7 +309,7 @@ describe.only('BinaryHeap unit tests', function () { it('Should return the smallest values as heap grows', function () { for (let i = 1; i <= values.length; ++i) { const vals = Array.from(values.slice(0, i)).sort(compareFn); - expect(empty.push(values[i-1])).to.equal(i); + expect(empty.push(values[i - 1])).to.equal(i); expect(empty.peek()).to.equal(vals[0]); expect(empty.size).to.equal(i); } @@ -255,7 +328,7 @@ describe.only('BinaryHeap unit tests', function () { } }); }); - describe('#pushPop()', function() { + describe('#pushPop()', function () { it('Should work when empty', function () { expect(empty.pushPop(1)).to.equal(1); expect(empty.peek()).to.equal(undefined); @@ -305,7 +378,7 @@ describe.only('BinaryHeap unit tests', function () { } }); }); - describe('#replace()', function() { + describe('#replace()', function () { it('Should work when empty', function () { expect(empty.replace(1)).to.equal(undefined); expect(empty.peek()).to.equal(1); @@ -335,7 +408,7 @@ describe.only('BinaryHeap unit tests', function () { expect(filled.size).to.equal(vals.length); vals.sort((a, b) => compareFn(b, a)); expect(filled.peek()).to.equal(vals[vals.length - 1]); - let expected = vals.pop()!; + const expected = vals.pop()!; expect(filled.replace(updatedValues[i])).to.equal(expected); vals.push(updatedValues[i]); } @@ -344,7 +417,7 @@ describe.only('BinaryHeap unit tests', function () { const vals = Array.from(values).sort((a, b) => compareFn(b, a)); for (let i = 0; i < updatedValues.length; ++i) { const heap = new BinaryHeap(compareFn, vals); - let expected = vals.pop()!; + const expected = vals.pop()!; expect(heap.replace(updatedValues[i])).to.equal(expected); vals.push(updatedValues[i]); vals.sort((a, b) => compareFn(b, a)); @@ -355,18 +428,18 @@ describe.only('BinaryHeap unit tests', function () { } }); }); - describe('#size()', function() { + describe('#size()', function () { it('Should be zero when empty', function () { expect(empty.size).to.equal(0); }); it('Should be accurate', function () { for (let i = 1; i <= values.length; ++i) { - expect(empty.push(values[i-1])).to.equal(i); + expect(empty.push(values[i - 1])).to.equal(i); expect(empty.size).to.equal(i); } }); }); - describe('#[Symbol.iterator]()', function() { + describe('#[Symbol.iterator]()', function () { it('Should work when empty', function () { expect(Array.from(empty)).to.eql([]); }); @@ -380,9 +453,9 @@ describe.only('BinaryHeap unit tests', function () { expect(actual).to.eql(expected); }); }); - describe('#update()', function() { + describe('#update()', function () { it('Should return false when empty', function () { - expect(empty.update(1,2)).to.equal(false); + expect(empty.update(1, 2)).to.equal(false); expect(empty.peek()).to.equal(undefined); expect(empty.size).to.equal(0); }); @@ -390,12 +463,12 @@ describe.only('BinaryHeap unit tests', function () { expect(filled.update(-99, 12)).to.equal(false); }); it('Should return true if found', function () { - for(let i = 0; i < values.length; ++i) { + for (let i = 0; i < values.length; ++i) { expect(filled.update(values[i], updatedValues[i])).to.equal(true); } }); it('Should not modify size', function () { - for(let i = 0; i < values.length; ++i) { + for (let i = 0; i < values.length; ++i) { filled.update(values[i], updatedValues[i]); expect(filled.size).to.equal(values.length); } @@ -430,4 +503,4 @@ describe.only('BinaryHeap unit tests', function () { } }); }); -}); \ No newline at end of file +}); diff --git a/test/heap/skewHeap.ts b/test/heap/skewHeap.ts new file mode 100644 index 0000000..526fe82 --- /dev/null +++ b/test/heap/skewHeap.ts @@ -0,0 +1,506 @@ +import { expect } from 'chai'; +import { randomFill, randomInt } from 'crypto'; +import { BinaryHeap } from 'src/heap'; +import { SkewHeap } from 'src/heap/skewHeap'; + +describe('SkewHeap unit tests', function () { + const compareFn = (a: number, b: number) => a - b; + let empty: SkewHeap; + let filled: SkewHeap; + const values = new Uint32Array(36); + const updatedValues = new Uint32Array(36); + + // eslint-disable-next-line + randomFill(values, (_) => {}); + // eslint-disable-next-line + randomFill(updatedValues, (_) => {}); + + beforeEach(function () { + empty = new SkewHeap(compareFn); + filled = new SkewHeap(compareFn, values); + }); + + describe('#addAll()', function () { + it('Should work when empty', function () { + expect(empty.addAll([3, 2, 1])).to.equal(3); + expect(empty.peek()).to.equal(1); + expect(empty.size).to.equal(3); + }); + it('Should work when not empty', function () { + expect(filled.addAll([-1, -2, -3])).to.equal(values.length + 3); + expect(filled.peek()).to.equal(-3); + expect(filled.size).to.equal(values.length + 3); + }); + it('Should not break heap', function () { + for (let i = 0; i <= values.length; ++i) { + const arr1 = Array.from(values.slice(0, i)); + for (let j = 0; j <= updatedValues.length; ++j) { + const arr2 = Array.from(updatedValues.slice(0, j)); + const heap = new SkewHeap(compareFn, arr1); + expect(heap.size).to.equal(arr1.length); + expect(heap.addAll(arr2)).to.equal(i + j); + const sorted = arr1.concat(arr2); + sorted.sort((a, b) => compareFn(b, a)); + expect(heap.size).to.equal(sorted.length); + for (let k = i + j - 1; k >= 0; --k) { + expect(heap.pop()).to.equal(sorted[k]); + expect(heap.size).to.equal(k); + } + } + } + }); + }); + describe('#clear()', function () { + it('Should clear when empty', function () { + empty.clear(); + expect(empty.size).to.equal(0); + expect(Array.from(empty.dump())).to.eql([]); + }); + it('Should clear when not empty', function () { + filled.clear(); + expect(filled.size).to.equal(0); + expect(Array.from(filled.dump())).to.eql([]); + }); + it('Should clear added value', function () { + empty.push(12); + empty.clear(); + expect(empty.size).to.equal(0); + expect(Array.from(empty.dump())).to.eql([]); + }); + it('Should clear added values', function () { + empty.push(1); + empty.push(2); + empty.push(3); + empty.clear(); + expect(empty.size).to.equal(0); + expect(Array.from(empty.dump())).to.eql([]); + }); + }); + describe('#contains()', function () { + it('Should return false when empty', function () { + expect(empty.contains(values[0])).to.equal(false); + }); + it('Should return false when not found', function () { + expect(filled.contains(-99)).to.equal(false); + }); + it('Should return true if found', function () { + for (let i = 0; i < values.length; ++i) { + expect(filled.contains(values[i])).to.equal(true); + } + }); + }); + describe('#delete()', function () { + it('Should return false when empty', function () { + expect(empty.delete(1)).to.equal(false); + expect(empty.peek()).to.equal(undefined); + expect(empty.size).to.equal(0); + }); + it('Should return false when not found', function () { + expect(filled.delete(-99)).to.equal(false); + expect(filled.size).to.equal(values.length); + }); + it('Should return true if found', function () { + for (let i = 0; i < values.length; ++i) { + expect(filled.delete(values[i])).to.equal(true); + } + }); + it('Should decrease size', function () { + for (let i = values.length - 1; i >= 0; --i) { + expect(filled.delete(values[i])).to.equal(true); + expect(filled.size).to.equal(i); + } + }); + it('Should update heap', function () { + empty.addAll([20, 15, 10, 5]); + empty.delete(10); + expect(empty.peek()).to.equal(5); + expect(empty.size).to.equal(3); + empty.delete(5); + expect(empty.peek()).to.equal(15); + expect(empty.size).to.equal(2); + empty.delete(20); + expect(empty.peek()).to.equal(15); + expect(empty.size).to.equal(1); + empty.delete(15); + expect(empty.peek()).to.equal(undefined); + expect(empty.size).to.equal(0); + }); + it('Should not break heap', function () { + const vals = Array.from(values); + for (let i = vals.length - 1; i >= 0; --i) { + const heap = new SkewHeap(compareFn, vals); + const val = vals.splice(randomInt(vals.length), 1)[0]; + expect(heap.delete(val)).to.equal(true); + expect(heap.size).to.equal(vals.length); + const sorted = Array.from(vals).sort((a, b) => compareFn(b, a)); + while (heap.size > 0) { + expect(heap.pop()).to.equal(sorted.pop()); + } + } + }); + }); + describe('#dump()', function () { + it('Should work when empty', function () { + expect(Array.from(empty.dump())).to.eql([]); + }); + it('Should work with single value', function () { + empty.push(12); + expect(Array.from(empty.dump())).to.eql([12]); + }); + it('Should return iterable on all elements', function () { + const expected = Array.from(values).sort(compareFn); + const actual = Array.from(filled.dump()).sort(compareFn); + expect(actual).to.eql(expected); + }); + }); + describe('#merge()', function () { + it('Should work when empty', function () { + expect(empty.merge(filled)).to.equal(empty); + expect(empty.peek()).to.equal(filled.peek()); + expect(empty.size).to.equal(filled.size); + }); + it('Should work when not empty', function () { + const heap = new SkewHeap(compareFn, filled.dump()); + expect(filled.merge(heap)).to.equal(filled); + expect(filled.peek()).to.equal(filled.peek()); + expect(filled.size).to.equal(2 * heap.size); + }); + it('Should work with BinaryHeap', function () { + for (let i = 0; i <= values.length; ++i) { + const arr1 = Array.from(values.slice(0, i)); + for (let j = 0; j <= updatedValues.length; ++j) { + const arr2 = Array.from(updatedValues.slice(0, j)); + const heap = new BinaryHeap(compareFn, arr1); + expect(heap.size).to.equal(arr1.length); + expect(heap.merge(new BinaryHeap(compareFn, arr2))).to.equal(heap); + expect(heap.size).to.equal(i + j); + const sorted = arr1.concat(arr2); + sorted.sort((a, b) => compareFn(b, a)); + expect(heap.size).to.equal(sorted.length); + for (let k = i + j - 1; k >= 0; --k) { + expect(heap.pop()).to.equal(sorted[k]); + expect(heap.size).to.equal(k); + } + } + } + }); + it('Should work with SkewHeap', function () { + for (let i = 0; i <= values.length; ++i) { + const arr1 = Array.from(values.slice(0, i)); + for (let j = 0; j <= updatedValues.length; ++j) { + const arr2 = Array.from(updatedValues.slice(0, j)); + const heap = new SkewHeap(compareFn, arr1); + expect(heap.size).to.equal(arr1.length); + expect(heap.merge(new SkewHeap(compareFn, arr2))).to.equal(heap); + expect(heap.size).to.equal(i + j); + const sorted = arr1.concat(arr2); + sorted.sort((a, b) => compareFn(b, a)); + expect(heap.size).to.equal(sorted.length); + for (let k = i + j - 1; k >= 0; --k) { + expect(heap.pop()).to.equal(sorted[k]); + expect(heap.size).to.equal(k); + } + } + } + }); + it('Should work with generic heap', async function () { + this.timeout(60000) + for (let i = 0; i <= values.length; ++i) { + const arr1 = Array.from(values.slice(0, i)); + for (let j = 0; j <= updatedValues.length; ++j) { + const arr2 = Array.from(updatedValues.slice(0, j)); + const heap = new BinaryHeap(compareFn, arr1); + expect(heap.size).to.equal(arr1.length); + const heap2 = { size: arr2.length, dump: () => arr2 } as any; + expect(heap.merge(heap2)).to.equal(heap); + expect(heap.size).to.equal(i + j); + const sorted = arr1.concat(arr2); + sorted.sort((a, b) => compareFn(b, a)); + expect(heap.size).to.equal(sorted.length); + for (let k = i + j - 1; k >= 0; --k) { + expect(heap.pop()).to.equal(sorted[k]); + expect(heap.size).to.equal(k); + } + } + } + }); + }); + describe('#peek()', function () { + it('Should return `undefined` when empty', function () { + expect(empty.peek()).to.equal(undefined); + expect(empty.peek()).to.equal(undefined); + }); + it('Should return the added value', function () { + empty.push(12); + expect(empty.peek()).to.equal(12); + }); + it('Should return the smallest value', function () { + empty.push(1); + empty.push(2); + expect(empty.peek()).to.equal(1); + }); + it('Should return the smallest values as heap grows', function () { + for (let i = 0; i < values.length; ++i) { + const vals = Array.from(values.slice(0, i + 1)).sort(compareFn); + empty.push(values[i]); + expect(empty.peek()).to.equal(vals[0]); + } + }); + it('Should return the smallest values as heap shrinks', function () { + const vals = Array.from(values).sort((a, b) => compareFn(b, a)); + for (let i = values.length; i > 0; --i) { + expect(filled.peek()).to.equal(vals[i - 1]); + filled.pop(); + vals.pop(); + } + }); + }); + describe('#pop()', function () { + it('Should work when empty', function () { + expect(empty.pop()).to.equal(undefined); + expect(empty.size).to.equal(0); + expect(empty.pop()).to.equal(undefined); + expect(empty.size).to.equal(0); + }); + it('Should remove the value from the list', function () { + empty.push(12); + expect(empty.size).to.equal(1); + expect(empty.pop()).to.equal(12); + expect(empty.size).to.equal(0); + expect(empty.pop()).to.equal(undefined); + expect(empty.size).to.equal(0); + }); + it('Should return the smallest values', function () { + empty.push(1); + empty.push(2); + expect(empty.size).to.equal(2); + expect(empty.pop()).to.equal(1); + expect(empty.size).to.equal(1); + expect(empty.pop()).to.equal(2); + expect(empty.size).to.equal(0); + }); + it('Should return the smallest values as heap shrinks', function () { + const vals = Array.from(values).sort((a, b) => compareFn(b, a)); + for (let i = values.length; i > 0; vals.pop()) { + expect(filled.pop()).to.equal(vals[--i]); + expect(filled.size).to.equal(i); + } + }); + }); + describe('#push()', function () { + it('Should work when empty', function () { + expect(empty.push(1)).to.equal(1); + expect(empty.peek()).to.equal(1); + expect(empty.size).to.equal(1); + }); + it('Should add the value to the list', function () { + expect(empty.push(12)).to.equal(1); + expect(empty.peek()).to.equal(12); + expect(empty.size).to.equal(1); + }); + it('Should return the smallest values', function () { + expect(empty.push(1)).to.equal(1); + expect(empty.peek()).to.equal(1); + expect(empty.size).to.equal(1); + expect(empty.push(2)).to.equal(2); + expect(empty.peek()).to.equal(1); + expect(empty.size).to.equal(2); + }); + it('Should return the smallest values as heap grows', function () { + for (let i = 1; i <= values.length; ++i) { + const vals = Array.from(values.slice(0, i)).sort(compareFn); + expect(empty.push(values[i - 1])).to.equal(i); + expect(empty.peek()).to.equal(vals[0]); + expect(empty.size).to.equal(i); + } + }); + it('Should not break heap', function () { + const vals: number[] = []; + for (let i = 0; i < values.length; ++i) { + const heap = new SkewHeap(compareFn, vals); + heap.push(values[i]); + vals.push(values[i]); + const sorted = Array.from(vals).sort((a, b) => compareFn(b, a)); + for (let j = i; j >= 0; --j) { + expect(heap.pop()).to.equal(sorted[j]); + expect(heap.size).to.equal(j); + } + } + }); + }); + describe('#pushPop()', function () { + it('Should work when empty', function () { + expect(empty.pushPop(1)).to.equal(1); + expect(empty.peek()).to.equal(undefined); + expect(empty.size).to.equal(0); + }); + it('Should return the smallest value', function () { + empty.push(12); + expect(empty.pushPop(1)).to.equal(1); + expect(empty.peek()).to.equal(12); + expect(empty.size).to.equal(1); + expect(empty.pushPop(15)).to.equal(12); + expect(empty.peek()).to.equal(15); + expect(empty.size).to.equal(1); + }); + it('Should not modify heap size', function () { + const sorted = Array.from(values).sort(compareFn); + expect(filled.pushPop(-12)).to.equal(-12); + expect(filled.peek()).to.equal(sorted[0]); + expect(filled.size).to.equal(values.length); + expect(filled.pushPop(sorted[0] + 1)).to.equal(sorted[0]); + expect(filled.peek()).to.equal(sorted[0] + 1); + expect(filled.size).to.equal(values.length); + }); + it('Should always return the smallest value', function () { + const vals = Array.from(values); + for (let i = 0; i < updatedValues.length; ++i) { + vals.push(updatedValues[i]); + vals.sort((a, b) => compareFn(b, a)); + const expected = vals.pop(); + expect(filled.pushPop(updatedValues[i])).to.equal(expected); + expect(filled.peek()).to.equal(vals[vals.length - 1]); + expect(filled.size).to.equal(vals.length); + } + }); + it('Should not break heap', function () { + const vals = Array.from(values); + for (let i = 0; i < updatedValues.length; ++i) { + const heap = new SkewHeap(compareFn, vals); + vals.push(updatedValues[i]); + vals.sort((a, b) => compareFn(b, a)); + const expected = vals.pop(); + expect(heap.pushPop(updatedValues[i])).to.equal(expected); + for (let j = vals.length - 1; j >= 0; --j) { + expect(heap.pop()).to.equal(vals[j]); + expect(heap.size).to.equal(j); + } + } + }); + }); + describe('#replace()', function () { + it('Should work when empty', function () { + expect(empty.replace(1)).to.equal(undefined); + expect(empty.peek()).to.equal(1); + expect(empty.size).to.equal(1); + }); + it('Should return the smallest value', function () { + empty.push(12); + expect(empty.replace(1)).to.equal(12); + expect(empty.peek()).to.equal(1); + expect(empty.size).to.equal(1); + expect(empty.replace(15)).to.equal(1); + expect(empty.peek()).to.equal(15); + expect(empty.size).to.equal(1); + }); + it('Should not modify heap size', function () { + const sorted = Array.from(values).sort(compareFn); + expect(filled.replace(-12)).to.equal(sorted[0]); + expect(filled.peek()).to.equal(-12); + expect(filled.size).to.equal(values.length); + expect(filled.replace(sorted[0] + 1)).to.equal(-12); + expect(filled.peek()).to.equal(sorted[0] + 1); + expect(filled.size).to.equal(values.length); + }); + it('Should always return the smallest value', function () { + const vals = Array.from(values); + for (let i = 0; i < updatedValues.length; ++i) { + expect(filled.size).to.equal(vals.length); + vals.sort((a, b) => compareFn(b, a)); + expect(filled.peek()).to.equal(vals[vals.length - 1]); + const expected = vals.pop()!; + expect(filled.replace(updatedValues[i])).to.equal(expected); + vals.push(updatedValues[i]); + } + }); + it('Should not break heap', function () { + const vals = Array.from(values).sort((a, b) => compareFn(b, a)); + for (let i = 0; i < updatedValues.length; ++i) { + const heap = new SkewHeap(compareFn, vals); + const expected = vals.pop()!; + expect(heap.replace(updatedValues[i])).to.equal(expected); + vals.push(updatedValues[i]); + vals.sort((a, b) => compareFn(b, a)); + for (let j = vals.length - 1; j >= 0; --j) { + expect(heap.pop()).to.equal(vals[j]); + expect(heap.size).to.equal(j); + } + } + }); + }); + describe('#size()', function () { + it('Should be zero when empty', function () { + expect(empty.size).to.equal(0); + }); + it('Should be accurate', function () { + for (let i = 1; i <= values.length; ++i) { + expect(empty.push(values[i - 1])).to.equal(i); + expect(empty.size).to.equal(i); + } + }); + }); + describe('#[Symbol.iterator]()', function () { + it('Should work when empty', function () { + expect(Array.from(empty)).to.eql([]); + }); + it('Should work with single value', function () { + empty.push(12); + expect(Array.from(empty)).to.eql([12]); + }); + it('Should return sorted iterable on all elements', function () { + const expected = Array.from(values).sort(compareFn); + const actual = Array.from(filled); + expect(actual).to.eql(expected); + }); + }); + describe('#update()', function () { + it('Should return false when empty', function () { + expect(empty.update(1, 2)).to.equal(false); + expect(empty.peek()).to.equal(undefined); + expect(empty.size).to.equal(0); + }); + it('Should return false when not found', function () { + expect(filled.update(-99, 12)).to.equal(false); + }); + it('Should return true if found', function () { + for (let i = 0; i < values.length; ++i) { + expect(filled.update(values[i], updatedValues[i])).to.equal(true); + } + }); + it('Should not modify size', function () { + for (let i = 0; i < values.length; ++i) { + filled.update(values[i], updatedValues[i]); + expect(filled.size).to.equal(values.length); + } + }); + it('Should update heap', function () { + empty.push(5); + empty.update(5, 7); + expect(empty.peek()).to.equal(7); + expect(empty.size).to.equal(1); + empty.update(7, 2); + expect(empty.peek()).to.equal(2); + expect(empty.size).to.equal(1); + empty.push(12); + expect(empty.peek()).to.equal(2); + expect(empty.size).to.equal(2); + empty.update(12, 1); + expect(empty.peek()).to.equal(1); + expect(empty.size).to.equal(2); + }); + it('Should not break heap', function () { + const vals = Array.from(values); + for (let i = 0; i < vals.length; ++i) { + const heap = new SkewHeap(compareFn, vals); + expect(heap.update(vals[i], updatedValues[i])).to.equal(true); + expect(heap.size).to.equal(vals.length); + vals[i] = updatedValues[i]; + const sorted = Array.from(vals).sort((a, b) => compareFn(b, a)); + for (let j = vals.length - 1; j >= 0; --j) { + expect(heap.pop()).to.equal(sorted.pop()); + expect(heap.size).to.equal(j); + } + } + }); + }); +}); diff --git a/test/heap/utils.ts b/test/heap/utils.ts index 2e8e699..4e9defd 100644 --- a/test/heap/utils.ts +++ b/test/heap/utils.ts @@ -1,15 +1,18 @@ import { expect } from 'chai'; import { randomFill, randomInt } from 'crypto'; -import { bubbleUp, heapify, sinkDown } from 'src/heap/utils'; +import { bubbleUp, heapify, sinkDown, skewMerge } from 'src/heap/utils'; -describe.only('Heap.utils unit tests', function () { - describe('#bubbleUp()', function() { +describe('Heap.utils unit tests', function () { + describe('#bubbleUp()', function () { it('TODO'); }); - describe('#heapify()', function() { + describe('#heapify()', function () { it('TODO'); }); - describe('#sinkDown()', function() { + describe('#sinkDown()', function () { it('TODO'); }); -}); \ No newline at end of file + describe('#skewMerge()', function () { + it('TODO'); + }); +}); diff --git a/test/list/arrayList.ts b/test/list/arrayList.ts index 639556b..d549dbd 100644 --- a/test/list/arrayList.ts +++ b/test/list/arrayList.ts @@ -1,11 +1,13 @@ import { expect } from 'chai'; import { randomFill, randomInt } from 'crypto'; +import { CompareFn } from 'src'; import { ArrayList } from 'src/list/arrayList'; -import { clamp, wrap } from 'src/list/utils'; +import { clamp, cwrap } from 'src/list/utils'; describe('ArrayList unit tests', function () { let empty: ArrayList; let filled: ArrayList; + const compareFn: CompareFn = (a, b) => a - b; const values = new Uint32Array(36); const updatedValues = new Uint32Array(36); @@ -199,7 +201,7 @@ describe('ArrayList unit tests', function () { } }); it('Should copy intended range', async function () { - this.timeout(0); + this.timeout(60000); for (let n = 10; n > 0; --n) { const i = randomInt(2 * values.length) - values.length; for (let min = -values.length; min < values.length; ++min) { @@ -457,7 +459,7 @@ describe('ArrayList unit tests', function () { }); it('Should fill until end of list if max not given', function () { for (let min = -values.length; min < values.length; ++min) { - const from = wrap(min, 0, values.length); + const from = cwrap(min, 0, values.length); const list = new ArrayList(values); const vals = Array.from(values); vals.splice(min, values.length - from, ...values.slice(min).reverse()); @@ -469,7 +471,7 @@ describe('ArrayList unit tests', function () { }); it('Should fill from start of list if min not given', function () { for (let max = -values.length; max < values.length; ++max) { - const to = wrap(max, 0, values.length); + const to = cwrap(max, 0, values.length); const list = new ArrayList(values); const vals = Array.from(values); vals.splice(0, to, ...values.slice(0, max).reverse()); @@ -482,8 +484,8 @@ describe('ArrayList unit tests', function () { it('Should reverse intended range', function () { for (let min = -values.length; min < values.length; ++min) { for (let max = -values.length; max < values.length; ++max) { - const from = wrap(min, 0, values.length); - const to = wrap(max, 0, values.length); + const from = cwrap(min, 0, values.length); + const to = cwrap(max, 0, values.length); const list = new ArrayList(values); const vals = Array.from(values); vals.splice(min, to - from, ...values.slice(min, max).reverse()); @@ -741,7 +743,7 @@ describe('ArrayList unit tests', function () { }); it('Should delete from start if no count', function () { for (let start = -filled.size; start < filled.size; ++start) { - const size = filled.size - wrap(start, 0, filled.size); + const size = filled.size - cwrap(start, 0, filled.size); const list = new ArrayList(filled); const deleted = list.splice(start); expect(list).to.not.equal(deleted); @@ -781,7 +783,7 @@ describe('ArrayList unit tests', function () { it('Should delete intended range', function () { for (let start = -filled.size; start < filled.size; ++start) { for (let count = 0; count < filled.size; ++count) { - const min = wrap(start, 0, filled.size); + const min = cwrap(start, 0, filled.size); const size = clamp(count, 0, filled.size - min); const list = new ArrayList(filled); const deleted = list.splice(start, count); @@ -809,12 +811,12 @@ describe('ArrayList unit tests', function () { } }); it('Should delete and add elements at intended index', async function () { - this.timeout(0); + this.timeout(60000); for (let start = -filled.size; start < filled.size; ++start) { for (let count = 0; count < filled.size; ++count) { for (let n = 10; n > 0; --n) { const items = updatedValues.slice(randomInt(updatedValues.length)); - const min = wrap(start, 0, filled.size); + const min = cwrap(start, 0, filled.size); const size = clamp(count, 0, filled.size - min); const list = new ArrayList(filled); const deleted = list.splice(start, count, items); @@ -846,6 +848,37 @@ describe('ArrayList unit tests', function () { expect(Array.from(list)).to.eql(vals); }); }); + describe('#sort()', function () { + it('Should work on an empty list', function () { + expect(empty.sort(compareFn)).to.equal(empty); + expect(empty.size).to.equal(0); + expect(Array.from(empty)).to.eql([]); + }); + it('Should sort the list', function () { + const vals: number[] = []; + for (let i = 0; i < values.length; ++i) { + const list = new ArrayList(vals); + vals.push(values[i]); + list.push(values[i]); + const sorted = Array.from(vals).sort(compareFn); + expect(list.sort(compareFn)).to.equal(list); + expect(list.size).to.equal(vals.length); + expect(Array.from(list)).to.eql(sorted); + } + }); + it('Should not break list', function () { + const vals: number[] = []; + for (let i = 0; i < values.length; ++i) { + const list = new ArrayList(vals); + vals.push(values[i]); + list.push(values[i]); + const reverse = Array.from(vals).sort((a, b) => compareFn(b, a)); + list.sort(compareFn).reverse(); + expect(list.size).to.equal(vals.length); + expect(Array.from(list)).to.eql(reverse); + } + }); + }); describe('#[Symbol.iterator]()', function () { it('Should return an array copy of the values', function () { const vals: number[] = []; @@ -909,7 +942,7 @@ describe('ArrayList unit tests', function () { }); it('Should update until end of list if max not given', function () { for (let min = -values.length; min < values.length; ++min) { - const size = values.length - wrap(min, 0, values.length); + const size = values.length - cwrap(min, 0, values.length); const list = new ArrayList(values); const res = list.update(min, undefined, (_, i) => updatedValues[i]); const vals = Array.from(values); @@ -921,7 +954,7 @@ describe('ArrayList unit tests', function () { }); it('Should update from start of list if min not given', function () { for (let max = -values.length; max < values.length; ++max) { - const size = wrap(max, 0, values.length); + const size = cwrap(max, 0, values.length); const list = new ArrayList(values); const res = list.update(undefined, max, (_, i) => updatedValues[i]); const vals = Array.from(values); @@ -934,7 +967,7 @@ describe('ArrayList unit tests', function () { it('Should update intended range', function () { for (let min = -values.length; min < values.length; ++min) { for (let max = -values.length; max < values.length; ++max) { - const size = wrap(max, 0, values.length) - wrap(min, 0, values.length); + const size = cwrap(max, 0, values.length) - cwrap(min, 0, values.length); const list = new ArrayList(values); const res = list.update(min, max, (_, i) => updatedValues[i]); const vals = Array.from(values); diff --git a/test/list/doublyLinkedList.ts b/test/list/doublyLinkedList.ts index 8596af9..d433920 100644 --- a/test/list/doublyLinkedList.ts +++ b/test/list/doublyLinkedList.ts @@ -1,11 +1,13 @@ import { expect } from 'chai'; import { randomFill, randomInt } from 'crypto'; +import { CompareFn } from 'src'; import { DoublyLinkedList } from 'src/list/doublyLinkedList'; -import { clamp, wrap } from 'src/list/utils'; +import { clamp, cwrap } from 'src/list/utils'; describe('DoublyLinkedList unit tests', function () { let empty: DoublyLinkedList; let filled: DoublyLinkedList; + const compareFn: CompareFn = (a, b) => a - b; const values = new Uint32Array(36); const updatedValues = new Uint32Array(36); @@ -199,7 +201,7 @@ describe('DoublyLinkedList unit tests', function () { } }); it('Should copy intended range', async function () { - this.timeout(0); + this.timeout(60000); for (let n = 10; n > 0; --n) { const i = randomInt(2 * values.length) - values.length; for (let min = -values.length; min < values.length; ++min) { @@ -457,7 +459,7 @@ describe('DoublyLinkedList unit tests', function () { }); it('Should fill until end of list if max not given', function () { for (let min = -values.length; min < values.length; ++min) { - const from = wrap(min, 0, values.length); + const from = cwrap(min, 0, values.length); const list = new DoublyLinkedList(values); const vals = Array.from(values); vals.splice(min, values.length - from, ...values.slice(min).reverse()); @@ -469,7 +471,7 @@ describe('DoublyLinkedList unit tests', function () { }); it('Should fill from start of list if min not given', function () { for (let max = -values.length; max < values.length; ++max) { - const to = wrap(max, 0, values.length); + const to = cwrap(max, 0, values.length); const list = new DoublyLinkedList(values); const vals = Array.from(values); vals.splice(0, to, ...values.slice(0, max).reverse()); @@ -482,8 +484,8 @@ describe('DoublyLinkedList unit tests', function () { it('Should reverse intended range', function () { for (let min = -values.length; min < values.length; ++min) { for (let max = -values.length; max < values.length; ++max) { - const from = wrap(min, 0, values.length); - const to = wrap(max, 0, values.length); + const from = cwrap(min, 0, values.length); + const to = cwrap(max, 0, values.length); const list = new DoublyLinkedList(values); const vals = Array.from(values); vals.splice(min, to - from, ...values.slice(min, max).reverse()); @@ -741,7 +743,7 @@ describe('DoublyLinkedList unit tests', function () { }); it('Should delete from start if no count', function () { for (let start = -filled.size; start < filled.size; ++start) { - const size = filled.size - wrap(start, 0, filled.size); + const size = filled.size - cwrap(start, 0, filled.size); const list = new DoublyLinkedList(filled); const deleted = list.splice(start); expect(list).to.not.equal(deleted); @@ -781,7 +783,7 @@ describe('DoublyLinkedList unit tests', function () { it('Should delete intended range', function () { for (let start = -filled.size; start < filled.size; ++start) { for (let count = 0; count < filled.size; ++count) { - const min = wrap(start, 0, filled.size); + const min = cwrap(start, 0, filled.size); const size = clamp(count, 0, filled.size - min); const list = new DoublyLinkedList(filled); const deleted = list.splice(start, count); @@ -809,12 +811,12 @@ describe('DoublyLinkedList unit tests', function () { } }); it('Should delete and add elements at intended index', async function () { - this.timeout(0); + this.timeout(60000); for (let start = -filled.size; start < filled.size; ++start) { for (let count = 0; count < filled.size; ++count) { for (let n = 10; n > 0; --n) { const items = updatedValues.slice(randomInt(updatedValues.length)); - const min = wrap(start, 0, filled.size); + const min = cwrap(start, 0, filled.size); const size = clamp(count, 0, filled.size - min); const list = new DoublyLinkedList(filled); const deleted = list.splice(start, count, items); @@ -846,6 +848,37 @@ describe('DoublyLinkedList unit tests', function () { expect(Array.from(list)).to.eql(vals); }); }); + describe('#sort()', function () { + it('Should work on an empty list', function () { + expect(empty.sort(compareFn)).to.equal(empty); + expect(empty.size).to.equal(0); + expect(Array.from(empty)).to.eql([]); + }); + it('Should sort the list', function () { + const vals: number[] = []; + for (let i = 0; i < values.length; ++i) { + const list = new DoublyLinkedList(vals); + vals.push(values[i]); + list.push(values[i]); + const sorted = Array.from(vals).sort(compareFn); + expect(list.sort(compareFn)).to.equal(list); + expect(list.size).to.equal(vals.length); + expect(Array.from(list)).to.eql(sorted); + } + }); + it('Should not break list', function () { + const vals: number[] = []; + for (let i = 0; i < values.length; ++i) { + const list = new DoublyLinkedList(vals); + vals.push(values[i]); + list.push(values[i]); + const reverse = Array.from(vals).sort((a, b) => compareFn(b, a)); + list.sort(compareFn).reverse(); + expect(list.size).to.equal(vals.length); + expect(Array.from(list)).to.eql(reverse); + } + }); + }); describe('#[Symbol.iterator]()', function () { it('Should return an array copy of the values', function () { const vals: number[] = []; @@ -909,7 +942,7 @@ describe('DoublyLinkedList unit tests', function () { }); it('Should update until end of list if max not given', function () { for (let min = -values.length; min < values.length; ++min) { - const size = values.length - wrap(min, 0, values.length); + const size = values.length - cwrap(min, 0, values.length); const list = new DoublyLinkedList(values); const res = list.update(min, undefined, (_, i) => updatedValues[i]); const vals = Array.from(values); @@ -921,7 +954,7 @@ describe('DoublyLinkedList unit tests', function () { }); it('Should update from start of list if min not given', function () { for (let max = -values.length; max < values.length; ++max) { - const size = wrap(max, 0, values.length); + const size = cwrap(max, 0, values.length); const list = new DoublyLinkedList(values); const res = list.update(undefined, max, (_, i) => updatedValues[i]); const vals = Array.from(values); @@ -934,7 +967,7 @@ describe('DoublyLinkedList unit tests', function () { it('Should update intended range', function () { for (let min = -values.length; min < values.length; ++min) { for (let max = -values.length; max < values.length; ++max) { - const size = wrap(max, 0, values.length) - wrap(min, 0, values.length); + const size = cwrap(max, 0, values.length) - cwrap(min, 0, values.length); const list = new DoublyLinkedList(values); const res = list.update(min, max, (_, i) => updatedValues[i]); const vals = Array.from(values); diff --git a/test/list/linkedList.ts b/test/list/linkedList.ts index 07e7fb7..9274013 100644 --- a/test/list/linkedList.ts +++ b/test/list/linkedList.ts @@ -1,11 +1,13 @@ import { expect } from 'chai'; import { randomFill, randomInt } from 'crypto'; +import { CompareFn } from 'src'; import { LinkedList } from 'src/list/linkedList'; -import { clamp, wrap } from 'src/list/utils'; +import { clamp, cwrap } from 'src/list/utils'; describe('LinkedList unit tests', function () { let empty: LinkedList; let filled: LinkedList; + const compareFn: CompareFn = (a, b) => a - b; const values = new Uint32Array(36); const updatedValues = new Uint32Array(36); @@ -199,7 +201,7 @@ describe('LinkedList unit tests', function () { } }); it('Should copy intended range', async function () { - this.timeout(0); + this.timeout(60000); for (let n = 10; n > 0; --n) { const i = randomInt(2 * values.length) - values.length; for (let min = -values.length; min < values.length; ++min) { @@ -457,7 +459,7 @@ describe('LinkedList unit tests', function () { }); it('Should fill until end of list if max not given', function () { for (let min = -values.length; min < values.length; ++min) { - const from = wrap(min, 0, values.length); + const from = cwrap(min, 0, values.length); const list = new LinkedList(values); const vals = Array.from(values); vals.splice(min, values.length - from, ...values.slice(min).reverse()); @@ -469,7 +471,7 @@ describe('LinkedList unit tests', function () { }); it('Should fill from start of list if min not given', function () { for (let max = -values.length; max < values.length; ++max) { - const to = wrap(max, 0, values.length); + const to = cwrap(max, 0, values.length); const list = new LinkedList(values); const vals = Array.from(values); vals.splice(0, to, ...values.slice(0, max).reverse()); @@ -482,8 +484,8 @@ describe('LinkedList unit tests', function () { it('Should reverse intended range', function () { for (let min = -values.length; min < values.length; ++min) { for (let max = -values.length; max < values.length; ++max) { - const from = wrap(min, 0, values.length); - const to = wrap(max, 0, values.length); + const from = cwrap(min, 0, values.length); + const to = cwrap(max, 0, values.length); const list = new LinkedList(values); const vals = Array.from(values); vals.splice(min, to - from, ...values.slice(min, max).reverse()); @@ -741,7 +743,7 @@ describe('LinkedList unit tests', function () { }); it('Should delete from start if no count', function () { for (let start = -filled.size; start < filled.size; ++start) { - const size = filled.size - wrap(start, 0, filled.size); + const size = filled.size - cwrap(start, 0, filled.size); const list = new LinkedList(filled); const deleted = list.splice(start); expect(list).to.not.equal(deleted); @@ -781,7 +783,7 @@ describe('LinkedList unit tests', function () { it('Should delete intended range', function () { for (let start = -filled.size; start < filled.size; ++start) { for (let count = 0; count < filled.size; ++count) { - const min = wrap(start, 0, filled.size); + const min = cwrap(start, 0, filled.size); const size = clamp(count, 0, filled.size - min); const list = new LinkedList(filled); const deleted = list.splice(start, count); @@ -809,12 +811,12 @@ describe('LinkedList unit tests', function () { } }); it('Should delete and add elements at intended index', async function () { - this.timeout(0); + this.timeout(60000); for (let start = -filled.size; start < filled.size; ++start) { for (let count = 0; count < filled.size; ++count) { for (let n = 10; n > 0; --n) { const items = updatedValues.slice(randomInt(updatedValues.length)); - const min = wrap(start, 0, filled.size); + const min = cwrap(start, 0, filled.size); const size = clamp(count, 0, filled.size - min); const list = new LinkedList(filled); const deleted = list.splice(start, count, items); @@ -846,6 +848,37 @@ describe('LinkedList unit tests', function () { expect(Array.from(list)).to.eql(vals); }); }); + describe('#sort()', function () { + it('Should work on an empty list', function () { + expect(empty.sort(compareFn)).to.equal(empty); + expect(empty.size).to.equal(0); + expect(Array.from(empty)).to.eql([]); + }); + it('Should sort the list', function () { + const vals: number[] = []; + for (let i = 0; i < values.length; ++i) { + const list = new LinkedList(vals); + vals.push(values[i]); + list.push(values[i]); + const sorted = Array.from(vals).sort(compareFn); + expect(list.sort(compareFn)).to.equal(list); + expect(list.size).to.equal(vals.length); + expect(Array.from(list)).to.eql(sorted); + } + }); + it('Should not break list', function () { + const vals: number[] = []; + for (let i = 0; i < values.length; ++i) { + const list = new LinkedList(vals); + vals.push(values[i]); + list.push(values[i]); + const reverse = Array.from(vals).sort((a, b) => compareFn(b, a)); + list.sort(compareFn).reverse(); + expect(list.size).to.equal(vals.length); + expect(Array.from(list)).to.eql(reverse); + } + }); + }); describe('#[Symbol.iterator]()', function () { it('Should return an array copy of the values', function () { const vals: number[] = []; @@ -909,7 +942,7 @@ describe('LinkedList unit tests', function () { }); it('Should update until end of list if max not given', function () { for (let min = -values.length; min < values.length; ++min) { - const size = values.length - wrap(min, 0, values.length); + const size = values.length - cwrap(min, 0, values.length); const list = new LinkedList(values); const res = list.update(min, undefined, (_, i) => updatedValues[i]); const vals = Array.from(values); @@ -921,7 +954,7 @@ describe('LinkedList unit tests', function () { }); it('Should update from start of list if min not given', function () { for (let max = -values.length; max < values.length; ++max) { - const size = wrap(max, 0, values.length); + const size = cwrap(max, 0, values.length); const list = new LinkedList(values); const res = list.update(undefined, max, (_, i) => updatedValues[i]); const vals = Array.from(values); @@ -934,7 +967,7 @@ describe('LinkedList unit tests', function () { it('Should update intended range', function () { for (let min = -values.length; min < values.length; ++min) { for (let max = -values.length; max < values.length; ++max) { - const size = wrap(max, 0, values.length) - wrap(min, 0, values.length); + const size = cwrap(max, 0, values.length) - cwrap(min, 0, values.length); const list = new LinkedList(values); const res = list.update(min, max, (_, i) => updatedValues[i]); const vals = Array.from(values); diff --git a/test/list/utils.ts b/test/list/utils.ts index 83c1b04..e5a24c6 100644 --- a/test/list/utils.ts +++ b/test/list/utils.ts @@ -1,15 +1,18 @@ import { expect } from 'chai'; import { randomFill, randomInt } from 'crypto'; -import { batch, clamp, wrap } from 'src/list/utils'; +import { batch, clamp, cwrap, mergeSort, mergeSorted, next, wrap } from 'src/list/utils'; -describe.only('List.utils unit tests', function () { - describe('#batch()', function() { +describe('List.utils unit tests', function () { + describe('#batch()', function () { it('TODO'); }); - describe('#clamp()', function() { + describe('#clamp()', function () { it('TODO'); }); - describe('#wrap()', function() { + describe('#cwrap()', function () { it('TODO'); }); -}); \ No newline at end of file + describe('#wrap()', function () { + it('TODO'); + }); +}); diff --git a/test/segmentTree/inOrderSegmentTree.ts b/test/segmentTree/inOrderSegmentTree.ts index 4ef354f..1946f3a 100644 --- a/test/segmentTree/inOrderSegmentTree.ts +++ b/test/segmentTree/inOrderSegmentTree.ts @@ -1,6 +1,6 @@ import { expect } from 'chai'; import { randomFill } from 'crypto'; -import { InOrderSegmentTree } from 'src/segmentTree/inOrderSegmentTree'; +import { InOrderSegmentTree } from 'src/TODO/segmentTree/inOrderSegmentTree'; describe('InOrderSegmentTree unit tests', function () { let empty: InOrderSegmentTree; @@ -232,7 +232,7 @@ describe('InOrderSegmentTree unit tests', function () { expect(() => empty.update(-5, 5, (v) => v)).to.throw(RangeError); }); it('Should correctly update a tree', async function () { - this.timeout(0); + this.timeout(60000); for (let size = 1; size <= values.length; ++size) { let max = size; for (let min = 0; max <= values.length; ++min, ++max) { diff --git a/test/segmentTree/levelOrderSegmentTree.ts b/test/segmentTree/levelOrderSegmentTree.ts index fbea089..4817a4d 100644 --- a/test/segmentTree/levelOrderSegmentTree.ts +++ b/test/segmentTree/levelOrderSegmentTree.ts @@ -1,6 +1,6 @@ import { expect } from 'chai'; import { randomFill } from 'crypto'; -import { LevelOrderSegmentTree } from 'src/segmentTree/levelOrderSegmentTree'; +import { LevelOrderSegmentTree } from 'src/TODO/segmentTree/levelOrderSegmentTree'; describe('LevelOrderSegmentTree unit tests', function () { let empty: LevelOrderSegmentTree; @@ -232,7 +232,7 @@ describe('LevelOrderSegmentTree unit tests', function () { expect(() => empty.update(-5, 5, (v) => v)).to.throw(RangeError); }); it('Should correctly update a tree', async function () { - this.timeout(0); + this.timeout(60000); for (let size = 1; size <= values.length; ++size) { let max = size; for (let min = 0; max <= values.length; ++min, ++max) { diff --git a/typedoc.docs.json b/typedoc.docs.json index 9064cd7..476bbd6 100644 --- a/typedoc.docs.json +++ b/typedoc.docs.json @@ -1,5 +1,7 @@ { "entryPoints": ["src/index.ts"], + "excludePrivate": true, + "excludeProtected": true, "includeVersion": true, "out": "docs", "readme": "none",