@avensio/shared
Version:
A lightweight and dependency-free collection of essential data structures and graph algorithms, written entirely in TypeScript. This library supports CommonJS, ESM, and browser environments, and includes utility functions for practical, everyday tasks in
2,134 lines • 88.7 kB
JavaScript
"use strict";
var __defProp = Object.defineProperty;
var __getOwnPropSymbols = Object.getOwnPropertySymbols;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __propIsEnum = Object.prototype.propertyIsEnumerable;
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
var __spreadValues = (a, b) => {
for (var prop in b || (b = {}))
if (__hasOwnProp.call(b, prop))
__defNormalProp(a, prop, b[prop]);
if (__getOwnPropSymbols)
for (var prop of __getOwnPropSymbols(b)) {
if (__propIsEnum.call(b, prop))
__defNormalProp(a, prop, b[prop]);
}
return a;
};
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
class Stack {
constructor(elements) {
__publicField(this, "arr", []);
__publicField(this, "size", 0);
__publicField(this, "comparator", null);
if (elements) {
for (const el of elements) {
this.push(el);
}
}
}
clear() {
this.arr.splice(0, this.arr.length);
this.size = 0;
}
isEmpty() {
return this.size === 0;
}
top() {
const top = this.arr[this.size - 1];
if (top === void 0) throw new Error("no such element");
return top;
}
pop() {
const top = this.arr.pop();
if (top === void 0) throw new Error("no such element");
this.size--;
return top;
}
push(e) {
if (e !== void 0) {
this.arr.push(e);
this.size++;
}
}
/**
* To use this method, a comparator must be set
* @param e
*/
contains(e) {
for (const _e of this) {
if (this.comparator(e, _e) === Ordering.EQ) return true;
}
return false;
}
[Symbol.iterator]() {
const stack = this;
let index = this.size - 1;
return {
next: () => {
let top;
if (index > -2) top = stack.arr[index--];
return {
done: index === -2,
value: top
};
}
};
}
add(e) {
this.push(e);
}
*reverseIterator() {
const tmp = [];
for (const e of this) {
tmp.push(e);
}
for (const e of tmp.reverse()) {
yield e;
}
}
sort(cmp) {
this.arr.sort(cmp || this.comparator);
}
}
class LinkedStack {
constructor(elements) {
__publicField(this, "_top");
__publicField(this, "size", 0);
__publicField(this, "comparator", null);
if (elements) {
for (const el of elements) {
this.push(el);
}
}
}
/**
* O(1)
* @param e
*/
push(e) {
if (e !== void 0) {
this._top = {
value: e,
prev: this._top
};
this.size++;
}
}
/**
* O(1)
*/
pop() {
const node = this._top;
if (node === void 0) throw new Error("no such element");
this._top = node.prev;
this.size--;
const value = node.value;
node.value = node.next = node.prev = void 0;
return value;
}
/**
* O(1)
*/
isEmpty() {
return this.size === 0;
}
/**
* O(1)
*/
top() {
if (this._top === void 0) throw new Error("no such element");
return this._top.value;
}
/**
* O(1)
*/
clear() {
this._top = void 0;
this.size = 0;
}
/**
* To use this method, a comparator must be set
* @param e
*/
contains(e) {
for (const _e of this) {
if (this.comparator(e, _e) === Ordering.EQ) return true;
}
return false;
}
/**
* O(size)
*/
[Symbol.iterator]() {
let top = this._top;
return {
next: () => {
const _top = top;
top = _top == null ? void 0 : _top.prev;
return {
done: _top === void 0,
value: _top == null ? void 0 : _top.value
};
}
};
}
add(e) {
this.push(e);
}
*reverseIterator() {
const tmp = [];
for (const e of this) {
tmp.push(e);
}
for (const e of tmp.reverse()) {
yield e;
}
}
sort(cmp) {
const sorted = quicksort(this, cmp || this.comparator, () => new LinkedStack());
this.clear();
for (const sortedElement of sorted) {
this.push(sortedElement);
}
}
}
class Queue {
constructor(elements, comparator) {
__publicField(this, "arr", []);
__publicField(this, "size", 0);
__publicField(this, "comparator", null);
if (elements) {
for (const el of elements) {
this.enqueue(el);
}
}
if (comparator) {
this.comparator = comparator;
this.sort();
}
}
clear() {
this.arr.splice(0, this.size);
this.size = 0;
}
dequeue() {
const head = this.arr.pop();
if (head === void 0) throw new Error("no such element");
this.size--;
return head;
}
enqueue(e) {
if (e !== void 0) {
this.arr.unshift(e);
this.size++;
}
}
add(e) {
this.enqueue(e);
}
isEmpty() {
return this.size === 0;
}
head() {
const head = this.arr[this.size - 1];
if (head === void 0) throw new Error("no such element");
return head;
}
[Symbol.iterator]() {
const queue = this;
let index = this.size - 1;
return {
next: () => {
let top;
if (index > -2) top = queue.arr[index--];
return {
done: index === -2,
value: top
};
}
};
}
*reverseIterator() {
for (let i = 0; i < this.size; i++) {
yield this.arr[i];
}
}
sort(cmp) {
const backupCmp = this.comparator;
if (cmp) {
this.comparator = cmp;
}
this.arr.sort(this.comparator).reverse();
this.comparator = backupCmp;
}
}
class LinkedQueue {
constructor(elements, comparator) {
__publicField(this, "_head");
__publicField(this, "tail");
__publicField(this, "size", 0);
__publicField(this, "comparator", null);
if (elements) {
for (const el of elements) {
this.enqueue(el);
}
}
if (comparator) {
this.comparator = comparator;
}
}
/**
* O(1)
* @param e
*/
enqueue(e) {
if (e === void 0) return;
const oldTail = this.tail;
this.tail = {
value: e,
next: void 0
};
if (this._head) oldTail.next = this.tail;
else this._head = this.tail;
this.size++;
}
add(e) {
this.enqueue(e);
}
/**
* O(1)
*/
dequeue() {
const head = this._head;
if (!this._head) throw new Error("no such element");
this._head = head.next;
this.size--;
const value = head.value;
if (this.isEmpty()) {
this.tail = this.tail.value = this.tail.next = this.tail.prev = void 0;
}
head.value = head.prev = head.next = void 0;
return value;
}
/**
* O(1)
*/
isEmpty() {
return this.size === 0;
}
/**
* O(1)
*/
head() {
if (this._head) return this._head.value;
throw new Error("no such element");
}
/**
* O(1)
*/
clear() {
this._head = void 0;
this.size = 0;
}
/**
* O(size)
*/
[Symbol.iterator]() {
let head = this._head;
return {
next: () => {
const _head = head;
head = _head == null ? void 0 : _head.next;
return {
done: _head == void 0,
value: _head == null ? void 0 : _head.value
};
}
};
}
*reverseIterator() {
const tmp = [];
for (const e of this) {
tmp.push(e);
}
for (const e of tmp.reverse()) {
yield e;
}
}
sort(cmp) {
const sorted = quicksort(this, cmp || this.comparator, () => new LinkedQueue());
this.clear();
for (const sortedElement of sorted) {
this.enqueue(sortedElement);
}
}
}
class PriorityQueue {
constructor(comparator, elements) {
__publicField(this, "size", 0);
__publicField(this, "comparator");
__publicField(this, "heap");
this.comparator = comparator;
this.heap = new FibonacciHeap(comparator);
if (elements) {
for (const e of elements) {
this.heap.insert(e);
this.size++;
}
}
}
enqueue(e) {
if (e !== void 0) {
this.heap.insert(e);
this.size++;
}
}
dequeue() {
const minNode = this.heap.extractMin();
this.size--;
const value = minNode.value;
minNode.value = minNode.parent = minNode.child = minNode.left = minNode.right = void 0;
return value;
}
head() {
if (this.size === 0) throw new Error("no such element");
return this.heap.minimum().value;
}
add(e) {
this.enqueue(e);
}
isEmpty() {
return this.size === 0;
}
clear() {
this.heap.clear();
this.size = 0;
}
[Symbol.iterator]() {
return this.heap[Symbol.iterator]();
}
*reverseIterator() {
const tmp = [];
for (const e of this) {
tmp.push(e);
}
for (const e of tmp.reverse()) {
yield e;
}
}
sort(cmp) {
this.heap.sort(cmp || this.comparator);
}
}
class Dequeue {
constructor(elements) {
__publicField(this, "size", 0);
__publicField(this, "_head");
__publicField(this, "tail");
__publicField(this, "comparator", null);
if (elements) {
for (const el of elements) {
this.enqueue(el);
}
}
}
/**
* O(1)
* @param e
*/
enqueue(e) {
if (e === void 0) return;
if (!this._head) {
this._head = { value: e };
} else if (!this.tail) {
this.tail = {
value: e,
prev: this._head
};
this._head.next = this.tail;
} else {
const newTail = {
value: e,
prev: this.tail
};
this.tail.next = newTail;
this.tail = newTail;
}
this.size++;
}
add(e) {
this.enqueue(e);
}
/**
* O(1)
*/
dequeue() {
if (this.size === 0) throw new Error("no such element");
const head = this._head;
this._head = head.next;
if (this._head) this._head.prev = void 0;
this.size--;
if (this.isEmpty()) this.tail = void 0;
return head.value;
}
/**
* O(1)
* @param e
*/
push(e) {
if (e !== void 0) {
if (!this._head) {
this._head = { value: e };
} else if (!this.tail) {
this.tail = this._head;
this.tail.next = void 0;
this._head = {
value: e,
next: this.tail
};
this.tail.prev = this._head;
} else {
const newHead = {
value: e,
next: this._head
};
this._head.prev = newHead;
this._head = newHead;
}
this.size++;
}
}
/**
* O(1)
*/
pop() {
if (this.size === 0) throw new Error("no such element");
let currentTail = this.tail;
if (!currentTail) {
currentTail = this._head;
this._head = void 0;
}
if (this.size === 2) {
currentTail = this.tail;
this.tail = this._head.next = void 0;
}
this.tail = currentTail.prev;
if (this.tail) this.tail.next = void 0;
this.size--;
return currentTail.value;
}
/**
* O(1)
*/
top() {
if (this.tail) return this.tail.value;
if (this._head) return this._head.value;
throw new Error("no such element");
}
/**
* O(1)
*/
head() {
if (this._head) return this._head.value;
throw new Error("no such element");
}
/**
* O(1)
*/
isEmpty() {
return this.size === 0;
}
/**
* O(1)
*/
clear() {
this._head = this.tail = void 0;
this.size = 0;
}
/**
* For this method to work, a comparator must be set
* @param e
*/
contains(e) {
for (const _e of this) {
if (this.comparator(e, _e) === Ordering.EQ) return true;
}
return false;
}
/**
* O(size)
*/
[Symbol.iterator]() {
let head = this._head;
return {
next: () => {
const _head = head;
head = _head == null ? void 0 : _head.next;
return {
done: _head == void 0,
value: _head == null ? void 0 : _head.value
};
}
};
}
/**
* O(size)
*/
*reverseIterator() {
if (!this.tail && !this._head) return;
if (!this.tail) {
yield this._head.value;
return;
}
let tail = this.tail;
yield tail == null ? void 0 : tail.value;
while ((tail == null ? void 0 : tail.prev) != void 0) {
tail = tail.prev;
yield tail.value;
}
}
sort(cmp) {
const sorted = quicksort(this, cmp || this.comparator, () => new Dequeue());
this.clear();
for (const sortedElement of sorted) {
this.enqueue(sortedElement);
}
}
}
class List {
constructor(elements) {
__publicField(this, "arr", []);
__publicField(this, "size", 0);
__publicField(this, "comparator", null);
if (elements) {
for (const el of elements) {
this.add(el);
}
}
}
add(e) {
if (e !== void 0) {
this.arr.push(e);
this.size++;
}
}
addAll(c) {
for (const e of c) {
this.add(e);
}
}
get(index) {
return this.arr[index];
}
set(index, e) {
if (index < 0 || index >= this.size || e === void 0) return false;
this.arr[index] = e;
return true;
}
/**
* A positive end index will result in slicing to the right, a negative end index in slicing to the left
* @param startIndex
* @param endIndex
*/
slice(startIndex, endIndex) {
const slice = new List();
let { start, end } = calculateStartAndEnd.call(this, startIndex, endIndex);
const count = calculateCount.call(this, start, end, true);
for (let i = 0; i < count; i++) {
slice.add(this.get(start % this.size));
start++;
}
return slice;
}
/**
* <p>With this variant of slice, the end index can be used as a direction value.</p>
* <p>When the end index is negative, then it will be sliced to the left.</p>
*
* @param startIndex
* @param endIndex
*/
slice2(startIndex, endIndex) {
const slice = new List();
if (startIndex < 0) {
let start = this.size + (startIndex % this.size === 0 ? -this.size : startIndex % this.size);
if (endIndex < 0) {
const end = this.size + (endIndex % this.size === 0 ? -this.size : endIndex % this.size);
const count = calculateCount.call(this, start, end);
for (let i = 0; i < count; i++) {
slice.add(this.get(start));
start--;
if (start < 0) {
start = this.size - 1;
}
}
} else {
const end = endIndex % this.size;
const count = calculateCount.call(this, start, end, true);
for (let i = 0; i < count; i++) {
slice.add(this.get(start % this.size));
start++;
}
}
} else {
let start = startIndex % this.size;
if (endIndex < 0) {
const end = this.size + endIndex % this.size;
const count = calculateCount.call(this, start, end);
for (let i = 0; i < count; i++) {
if (start < 0) {
slice.add(this.get(this.size + start));
} else {
slice.add(this.get(start));
}
start--;
}
} else {
const end = endIndex % this.size;
const count = calculateCount.call(this, start, end, true);
for (let i = 0; i < count; i++) {
slice.add(this.get(start % this.size));
start++;
}
}
}
return slice;
}
/**
* <p>A negative delete count will result in slicing to the left</p>
* <p>A negative start count will be mapped to <code>this.size - startIndex</code></p>
* <p>f.e. (size = 6) -1 -> 5, -2 -> 4, ...</p>
* @param startIndex
* @param deleteCount
*/
splice(startIndex, deleteCount) {
return _splice.call(this, startIndex, deleteCount, new List());
}
map(fn) {
const list = new List();
for (const e of this) {
list.add(fn(e));
}
return list;
}
reduce(fn, initialValue) {
return this.arr.reduce(fn, initialValue || {});
}
filter(predicate) {
const list = new List();
for (const e of this) {
if (predicate(e)) {
list.add(e);
}
}
return list;
}
every(predicate) {
let all = true;
for (const e of this.arr) {
if (!predicate(e)) {
all = false;
break;
}
}
return all;
}
some(predicate) {
let someMatches = false;
for (const e of this.arr) {
if (predicate(e)) {
someMatches = true;
break;
}
}
return someMatches;
}
isEmpty() {
return this.size === 0;
}
clear() {
this.arr.splice(0, this.arr.length);
this.size = 0;
}
remove(index) {
const slice = this.arr.splice(index, 1);
if (slice.length === 1) {
this.size--;
return slice[0];
}
throw new Error("no such element");
}
/**
* For this method to work, a comparator must be set
* @param e
*/
includes(e) {
return this.indexOf(e) > -1;
}
/**
* For this method to work, a comparator must be set
* @param l
*/
equals(l) {
for (let i = 0; i < l.size; i++) {
if (this.comparator(l.get(i), this.get(i)) !== Ordering.EQ) {
return false;
}
}
return true;
}
/**
* Finds the first index of the element
* @param e
*/
indexOf(e) {
for (let i = 0; i < this.size; i++) {
if (this.comparator(e, this.get(i)) === Ordering.EQ) return i;
}
return -1;
}
sort(cmp) {
const backupCmp = this.comparator;
if (cmp) {
this.comparator = cmp;
}
this.arr.sort(this.comparator);
this.comparator = backupCmp;
}
*reverseIterator() {
for (let i = this.arr.length - 1; i >= 0; i--) {
yield this.arr[i];
}
}
[Symbol.iterator]() {
let index = 0;
return {
next: () => {
let el;
try {
el = this.get(index);
} catch (e) {
}
return {
done: index++ === this.size,
value: el
};
}
};
}
}
class LinkedList {
constructor(elements, reverse = false) {
__publicField(this, "first");
__publicField(this, "last");
__publicField(this, "size", 0);
__publicField(this, "comparator", null);
if (elements) {
for (const el of elements) {
if (reverse) this.addFirst(el);
else this.add(el);
}
}
}
/**
* O(1)
* @param e
*/
add(e) {
this.addLast(e);
}
addAll(c) {
for (const e of c) {
this.add(e);
}
}
/**
* O(1)
* @param e
*/
addFirst(e) {
if (e === void 0) return;
this.first = {
value: e,
next: this.first
};
if (this.size === 1) {
this.last = this.first.next;
}
this.size++;
}
/**
* O(1)
* @param e
*/
addLast(e) {
if (e === void 0) return;
const node = { value: e };
if (!this.first) {
this.first = node;
} else if (this.first && !this.last) {
this.last = node;
this.first.next = this.last;
} else if (this.last) {
this.last.next = node;
this.last = this.last.next;
}
this.size++;
}
/**
* O(1)
*/
clear() {
this.first = this.last = void 0;
this.size = 0;
}
/**
* O(size)<br>
* Ω(1)
*/
get(index) {
try {
const node = this.getNode(index);
if (node) {
return node.value;
}
} catch (e) {
}
return void 0;
}
/**
* O(size)<br>
* Ω(1)
*/
set(index, e) {
if (index < 0 || index >= this.size || e === void 0) return false;
this.getNode(index).value = e;
return true;
}
slice(startIndex, endIndex) {
return _slice.call(this, startIndex, endIndex, new LinkedList());
}
slice2(startIndex, endIndex) {
const slice = new LinkedList();
if (startIndex < 0) {
let start = this.size + (startIndex % this.size === 0 ? -this.size : startIndex % this.size);
if (endIndex < 0) {
const end = this.size + (endIndex % this.size === 0 ? -this.size : endIndex % this.size);
const count = calculateCount.call(this, start, end);
for (let i = 0; i < count; i++) {
if (start < 0) {
slice.add(this.get(this.size + start));
} else {
slice.add(this.get(start));
}
start--;
}
} else {
const end = endIndex % this.size;
const count = calculateCount.call(this, start, end, true);
let startNode = this.getNode(start);
for (let i = 0; i < count; i++) {
slice.add(startNode == null ? void 0 : startNode.value);
startNode = (startNode == null ? void 0 : startNode.next) || this.first;
start++;
}
}
} else {
let start = startIndex % this.size;
if (endIndex < 0) {
const end = this.size + endIndex % this.size;
const count = calculateCount.call(this, start, end);
for (let i = 0; i < count; i++) {
if (start < 0) {
slice.add(this.get(this.size + start));
} else {
slice.add(this.get(start));
}
start--;
}
} else {
const end = endIndex % this.size;
const count = calculateCount.call(this, start, end, true);
let startNode = this.getNode(start);
for (let i = 0; i < count; i++) {
slice.add(startNode == null ? void 0 : startNode.value);
startNode = (startNode == null ? void 0 : startNode.next) || this.first;
start++;
}
}
}
return slice;
}
splice(startIndex, deleteCount) {
return _splice.call(this, startIndex, deleteCount, new LinkedList());
}
map(fn) {
const list = new LinkedList();
for (const e of this) {
list.add(fn(e));
}
return list;
}
reduce(fn, initialValue) {
let result = initialValue || {};
for (const e of this) {
result = fn(result, e);
}
return result;
}
filter(predicate) {
const list = new LinkedList();
for (const e of this) {
if (predicate(e)) {
list.add(e);
}
}
return list;
}
every(predicate) {
let all = true;
for (const el of this) {
if (!predicate(el)) {
all = false;
break;
}
}
return all;
}
some(predicate) {
let someMatches = false;
for (const e of this) {
if (predicate(e)) {
someMatches = true;
break;
}
}
return someMatches;
}
/**
* O(1)
*/
getFirst() {
if (!this.first) throw new Error("no such element");
return this.first.value;
}
/**
* O(1)
*/
getLast() {
if (this.size === 1) return this.first.value;
if (!this.last) throw new Error("no such element");
return this.last.value;
}
/**
* O(1)
*/
isEmpty() {
return this.size === 0;
}
/**
* O(size)<br>
* Ω(1)
* @param index
*/
remove(index) {
var _a;
if (index >= this.size || index < 0)
throw new Error("no such element");
let toRemove;
let value;
switch (index) {
case 0:
return this.removeFirst();
case this.size - 1:
return this.removeLast();
case 1:
toRemove = this.getNode(1);
this.first.next = toRemove.next;
value = toRemove.value;
toRemove.next = toRemove.value = void 0;
break;
default:
const prevNode = this.getNode(index - 1);
toRemove = prevNode == null ? void 0 : prevNode.next;
prevNode.next = (_a = prevNode == null ? void 0 : prevNode.next) == null ? void 0 : _a.next;
value = toRemove.value;
toRemove.next = toRemove.value = void 0;
break;
}
this.size--;
return value;
}
/**
* O(1)
*/
removeFirst() {
let value;
switch (this.size) {
case 0:
throw new Error("no such element");
case 1:
const _first1 = this.first;
this.first = void 0;
value = _first1.value;
_first1.next = _first1.value = void 0;
break;
case 2:
const _first2 = this.first;
this.first = this.last;
this.last = void 0;
value = _first2.value;
_first2.next = _first2.value = void 0;
break;
default:
const _first3 = this.first;
this.first = {
value: _first3.next.value,
next: _first3.next.next
};
value = _first3.value;
_first3.next = _first3.value = void 0;
}
this.size--;
return value;
}
/**
* O(size)<br>
* Ω(1)
*/
removeLast() {
let value;
switch (this.size) {
case 0:
throw new Error("no such element");
case 1:
const _last1 = this.first;
this.first = void 0;
value = _last1.value;
_last1.value = _last1.next = void 0;
break;
case 2:
const _last2 = this.last;
this.first.next = this.last = void 0;
value = _last2.value;
_last2.value = _last2.next = void 0;
break;
default:
const _last3 = this.last;
this.last = this.getNode(this.size - 2);
this.last.next = void 0;
value = _last3.value;
_last3.value = _last3.next = void 0;
}
this.size--;
return value;
}
/**
* O(index + 1)<br>
* Ω(1)
* @param index
*/
getNode(index) {
if (index < 0 || index >= this.size) throw new Error("no such element");
let node = this.first;
for (let i = 0; i < index; i++) {
node = node.next;
}
return node;
}
/**
* For this method to work, a comparator must be set
* @param e
*/
includes(e) {
return this.indexOf(e) > -1;
}
/**
* For this method to work, a comparator must be set
* @param l
*/
equals(l) {
for (let i = 0; i < l.size; i++) {
if (this.comparator(l.get(i), this.get(i)) !== Ordering.EQ) {
return false;
}
}
return true;
}
indexOf(e) {
for (let i = 0; i < this.size; i++) {
if (this.comparator(e, this.get(i)) === Ordering.EQ) return i;
}
return -1;
}
sort(cmp) {
const backupCmp = this.comparator;
if (cmp) {
this.comparator = cmp;
}
const sorted = heapSort(this, this.comparator);
this.clear();
for (const sortedElement of sorted) {
this.add(sortedElement);
}
this.comparator = backupCmp;
}
/**
* O(∑ i=1 to size (i))
* Ω(1)
*/
*reverseIterator() {
for (let i = this.size - 1; i >= 0; i--) {
yield this.getNode(i).value;
}
}
/**
* O(size)
*/
[Symbol.iterator]() {
let first = this.first;
return {
next: () => {
return {
done: first === void 0,
value: (() => {
if (first) {
const val = first.value;
first = first.next;
return val;
}
return void 0;
})()
};
}
};
}
}
class DoublyLinkedList {
constructor(elements, reverse = false) {
__publicField(this, "first");
__publicField(this, "last");
__publicField(this, "size", 0);
__publicField(this, "comparator", null);
if (elements) {
for (const el of elements) {
if (reverse) this.addFirst(el);
else this.add(el);
}
}
}
/**
* O(1)
* @param e
*/
add(e) {
this.addLast(e);
}
addAll(c) {
for (const e of c) {
this.add(e);
}
}
/**
* O(1)
* @param e
*/
addFirst(e) {
if (e === void 0) return;
const oldFirst = this.first;
this.first = {
value: e,
next: oldFirst
};
if (this.first.next) {
this.first.next.prev = this.first;
}
if (this.size === 1) {
this.last = this.first.next;
this.last.prev = this.first;
}
this.size++;
}
/**
* O(1)
* @param e
*/
addLast(e) {
if (e === void 0) return;
const node = { value: e };
if (!this.first) {
this.first = node;
} else if (this.first && !this.last) {
this.last = node;
this.first.next = this.last;
this.last.prev = this.first;
} else if (this.last) {
const oldLast = this.last;
this.last.next = node;
this.last = node;
this.last.prev = oldLast;
}
this.size++;
}
/**
* O(1)
*/
clear() {
this.first = this.last = void 0;
this.size = 0;
}
/**
* O(size / 2)<br>
* Ω(1)
* @param index
*/
get(index) {
try {
const node = this.getNode(index);
if (node) {
return node.value;
}
} catch (e) {
}
return void 0;
}
/**
* O(size / 2)<br>
* Ω(1)
* @param index
* @param e
*/
set(index, e) {
if (index < 0 || index >= this.size || e === void 0) return false;
this.getNode(index).value = e;
return true;
}
slice(startIndex, endIndex) {
return _slice.call(this, startIndex, endIndex, new DoublyLinkedList());
}
slice2(startIndex, endIndex) {
const slice = new DoublyLinkedList();
if (startIndex < 0) {
let start = this.size + (startIndex % this.size === 0 ? -this.size : startIndex % this.size);
if (endIndex < 0) {
const end = this.size + (endIndex % this.size === 0 ? -this.size : endIndex % this.size);
const count = calculateCount.call(this, start, end);
let startNode = this.getNode(start);
for (let i = 0; i < count; i++) {
slice.add(startNode == null ? void 0 : startNode.value);
startNode = (startNode == null ? void 0 : startNode.prev) || this.last;
}
} else {
const end = endIndex % this.size;
const count = calculateCount.call(this, start, end, true);
let startNode = this.getNode(start);
for (let i = 0; i < count; i++) {
slice.add(startNode == null ? void 0 : startNode.value);
startNode = (startNode == null ? void 0 : startNode.next) || this.first;
start++;
}
}
} else {
let start = startIndex % this.size;
if (endIndex < 0) {
const end = this.size + endIndex % this.size;
const count = calculateCount.call(this, start, end);
let startNode = this.getNode(start);
for (let i = 0; i < count; i++) {
slice.add(startNode == null ? void 0 : startNode.value);
startNode = (startNode == null ? void 0 : startNode.prev) || this.last;
start--;
}
} else {
const end = endIndex % this.size;
const count = calculateCount.call(this, start, end, true);
let startNode = this.getNode(start);
for (let i = 0; i < count; i++) {
slice.add(startNode == null ? void 0 : startNode.value);
startNode = (startNode == null ? void 0 : startNode.next) || this.first;
start++;
}
}
}
return slice;
}
splice(startIndex, deleteCount) {
return _splice.call(this, startIndex, deleteCount, new DoublyLinkedList());
}
map(fn) {
const list = new DoublyLinkedList();
for (const e of this) {
list.add(fn(e));
}
return list;
}
reduce(fn, initialValue) {
let result = initialValue || {};
for (const e of this) {
result = fn(result, e);
}
return result;
}
filter(predicate) {
const list = new DoublyLinkedList();
for (const e of this) {
if (predicate(e)) {
list.add(e);
}
}
return list;
}
every(predicate) {
let all = true;
for (const el of this) {
if (!predicate(el)) {
all = false;
break;
}
}
return all;
}
some(predicate) {
let someMatches = false;
for (const e of this) {
if (predicate(e)) {
someMatches = true;
break;
}
}
return someMatches;
}
/**
* O(1)
*/
getFirst() {
if (!this.first) throw new Error("no such element");
return this.first.value;
}
/**
* O(1)
*/
getLast() {
if (this.size === 1) return this.first.value;
if (!this.last) throw new Error("no such element");
return this.last.value;
}
/**
* O(1)
*/
isEmpty() {
return this.size === 0;
}
/**
* O(size / 2)<br>
* Ω(1)
* @param index
*/
remove(index) {
if (index >= this.size || index < 0) throw new Error("no such element");
let value;
switch (index) {
case 0:
return this.removeFirst();
case this.size - 1:
return this.removeLast();
case 1:
const toRemove = this.getNode(index);
this.first.next = toRemove.next;
this.first.next.prev = this.first;
value = toRemove.value;
toRemove.prev = toRemove.next = toRemove.value = void 0;
break;
default:
const toRemove2 = this.getNode(index);
toRemove2.prev.next = toRemove2.next;
toRemove2.next.prev = toRemove2.prev;
value = toRemove2.value;
toRemove2.next = toRemove2.prev = toRemove2.value = void 0;
}
this.size--;
return value;
}
/**
* O(1)
*/
removeFirst() {
let value;
switch (this.size) {
case 0:
throw new Error("no such element");
case 1:
const _first1 = this.first;
this.first = void 0;
value = _first1.value;
_first1.value = _first1.next = _first1.prev = void 0;
break;
case 2:
const _first2 = this.first;
this.first = this.last;
this.first.next = this.first.prev = void 0;
this.last = void 0;
value = _first2.value;
_first2.value = _first2.next = _first2.prev = void 0;
break;
default:
const _first3 = this.first;
this.first = {
value: this.first.next.value,
next: this.first.next.next
};
this.first.next.prev = this.first;
value = _first3.value;
_first3.value = _first3.next = _first3.prev = void 0;
}
this.size--;
return value;
}
/**
* O(1)
*/
removeLast() {
let value;
switch (this.size) {
case 0:
throw new Error("no such element");
case 1:
value = this.first.value;
this.first = this.first.value = void 0;
break;
case 2:
value = this.last.value;
this.first.next = this.last = this.last.prev = void 0;
break;
default:
value = this.last.value;
this.last = this.getNode(this.size - 2);
this.last.next = this.last.next.prev = void 0;
}
this.size--;
return value;
}
/**
* O(size / 2)<br>
* Ω(1)
* @param index
*/
getNode(index) {
if (index >= this.size || index < 0) throw new Error("no such element");
let node = this.first;
if (index > this.size / 2) {
node = this.last;
for (let i = this.size - 1; i > index; i--) {
node = node.prev;
}
} else {
for (let i = 0; i < index; i++) {
node = node.next;
}
}
return node;
}
/**
* For this method to work, a comparator must be set
* @param e
*/
includes(e) {
return this.indexOf(e) > -1;
}
/**
* For this method to work, a comparator must be set
* @param l
*/
equals(l) {
for (let i = 0; i < l.size; i++) {
if (this.comparator(l.get(i), this.get(i)) !== Ordering.EQ) {
return false;
}
}
return true;
}
indexOf(e) {
for (let i = 0; i < this.size; i++) {
if (this.comparator(e, this.get(i)) === Ordering.EQ) return i;
}
return -1;
}
sort(cmp) {
const backupCmp = this.comparator;
if (cmp) {
this.comparator = cmp;
}
const sorted = heapSort(this, this.comparator);
this.clear();
for (const sortedElement of sorted) {
this.add(sortedElement);
}
this.comparator = backupCmp;
}
/**
* In even cases: O(∑ i=1 to ⌊size÷2⌋ (i*2))<br>
* In odd cases: O((∑ i=1 to ⌊size÷2⌋ (i*2)) + ⌈size÷2⌉)<br>
* Ω(1)
*/
*reverseIterator() {
for (let i = this.size - 1; i >= 0; i--) {
yield this.getNode(i).value;
}
}
/**
* O(size)
*/
[Symbol.iterator]() {
let first = this.first;
return {
next: () => {
return {
done: first === void 0,
value: (() => {
if (first) {
const val = first.value;
first = first.next;
return val;
}
return void 0;
})()
};
}
};
}
}
class CyclicDoublyLinkedList {
constructor(elements, reverse = false) {
__publicField(this, "first");
__publicField(this, "last");
__publicField(this, "size", 0);
__publicField(this, "comparator", null);
if (elements) {
for (const el of elements) {
if (reverse) this.addFirst(el);
else this.add(el);
}
}
}
/**
* O(1)
* @param e
*/
add(e) {
this.addLast(e);
}
addAll(c) {
for (const e of c) {
this.add(e);
}
}
/**
* O(1)
* @param e
*/
addFirst(e) {
if (e === void 0) return;
const oldFirst = this.first;
this.first = {
value: e,
next: oldFirst,
prev: this.last
};
if (oldFirst) {
oldFirst.prev = this.first;
} else {
this.first.next = this.first;
}
if (!this.first.prev) {
this.first.prev = this.first;
} else {
this.last.next = this.first;
}
if (this.size === 1) {
this.last = this.first.next;
this.last.prev = this.first;
}
this.size++;
}
/**
* O(1)
* @param e
*/
addLast(e) {
if (e === void 0) return;
const node = { value: e };
if (!this.first) {
this.first = node;
this.first.next = this.first.prev = this.first;
} else if (this.first && !this.last) {
this.last = node;
this.last.prev = this.last.next = this.first;
this.first.next = this.first.prev = this.last;
} else if (this.last) {
const oldLast = this.last;
this.last.next = node;
this.last = node;
this.last.prev = oldLast;
this.last.next = this.first;
this.first.prev = this.last;
}
this.size++;
}
/**
* O(1)
*/
clear() {
this.first = this.last = void 0;
this.size = 0;
}
/**
* O(size / 2)<br>
* Ω(1)
* @param index
*/
get(index) {
try {
const node = this.getNode(index);
if (node) {
return node.value;
}
} catch (e) {
}
return void 0;
}
/**
* O(size / 2)<br>
* Ω(1)
* @param index
* @param e
*/
set(index, e) {
if (index < 0 || index >= this.size || e === void 0) return false;
this.getNode(index).value = e;
return true;
}
slice(startIndex, endIndex) {
return _slice.call(this, startIndex, endIndex, new CyclicDoublyLinkedList());
}
slice2(startIndex, endIndex) {
const slice = new CyclicDoublyLinkedList();
if (startIndex < 0) {
const start = this.size + (startIndex % this.size === 0 ? -this.size : startIndex % this.size);
if (endIndex < 0) {
const end = this.size + (endIndex % this.size === 0 ? -this.size : endIndex % this.size);
const count = calculateCount.call(this, start, end);
let startNode = this.getNode(start);
for (let i = 0; i < count; i++) {
slice.add(startNode == null ? void 0 : startNode.value);
startNode = startNode == null ? void 0 : startNode.prev;
}
} else {
const end = endIndex % this.size;
const count = calculateCount.call(this, start, end, true);
let startNode = this.getNode(start);
for (let i = 0; i < count; i++) {
slice.add(startNode == null ? void 0 : startNode.value);
startNode = startNode == null ? void 0 : startNode.next;
}
}
} else {
const start = startIndex % this.size;
if (endIndex < 0) {
const end = this.size + endIndex % this.size;
const count = calculateCount.call(this, start, end);
let startNode = this.getNode(start);
for (let i = 0; i < count; i++) {
slice.add(startNode == null ? void 0 : startNode.value);
startNode = startNode == null ? void 0 : startNode.prev;
}
} else {
const end = endIndex % this.size;
const count = calculateCount.call(this, start, end, true);
let startNode = this.getNode(start);
for (let i = 0; i < count; i++) {
slice.add(startNode == null ? void 0 : startNode.value);
startNode = startNode == null ? void 0 : startNode.next;
}
}
}
return slice;
}
splice(startIndex, deleteCount) {
return _splice.call(this, startIndex, deleteCount, new CyclicDoublyLinkedList());
}
map(fn) {
const list = new CyclicDoublyLinkedList();
for (const e of this) {
list.add(fn(e));
}
return list;
}
reduce(fn, initialValue) {
let result = initialValue || {};
for (const e of this) {
result = fn(result, e);
}
return result;
}
filter(predicate) {
const list = new CyclicDoublyLinkedList();
for (const e of this) {
if (predicate(e)) {
list.add(e);
}
}
return list;
}
every(predicate) {
let all = true;
for (const el of this) {
if (!predicate(el)) {
all = false;
break;
}
}
return all;
}
some(predicate) {
let someMatches = false;
for (const e of this) {
if (predicate(e)) {
someMatches = true;
break;
}
}
return someMatches;
}
/**
* O(1)
*/
getFirst() {
if (!this.first) throw new Error("no such element");
return this.first.value;
}
/**
* O(1)
*/
getLast() {
if (this.size === 1) return this.first.value;
if (!this.last) throw new Error("no such element");
return this.last.value;
}
/**
* O(1)
*/
isEmpty() {
return this.size === 0;
}
/**
* O(size / 2)<br>
* Ω(1)
* @param index
*/
remove(index) {
if (index >= this.size || index < 0) throw new Error("no such element");
let value;
switch (index) {
case 0:
return this.removeFirst();
case this.size - 1:
return this.removeLast();
case 1:
const toRemove = this.getNode(index);
this.first.next = toRemove.next;
this.first.next.prev = this.first;
value = toRemove.value;
toRemove.next = toRemove.prev = toRemove.value = void 0;
break;
default:
const toRemove2 = this.getNode(index);
toRemove2.prev.next = toRemove2.next;
toRemove2.next.prev = toRemove2.prev;
value = toRemove2.value;
toRemove2.next = toRemove2.prev = toRemove2.value = void 0;
}
this.size--;
return value;
}
/**
* O(1)
*/
removeFirst() {
let value;
switch (this.size) {
case 0:
throw new Error("no such element");
case 1:
const _first1 = this.first;
this.first = void 0;
value = _first1.value;
_first1.value = _first1.next = _first1.prev = void 0;
break;
case 2:
const _first2 = this.first;
this.last.next = this.last.prev = void 0;
this.first = this.last;
this.last = void 0;
this.first.next = this.first.prev = this.first;
value = _first2.value;
_first2.value = _first2.next = _first2.prev = void 0;
break;
default:
const _first3 = this.first;
this.first = {
value: _first3.next.value,
next: _first3.next.next,
prev: _first3.next.prev
};
this.first.next.prev = this.first;
value = _first3.value;
_first3.prev = _first3.next = _first3.value = void 0;
}
this.size--;
return value;
}
/**
* O(size / 2)<br>
* Ω(1)
*/
removeLast() {
let value;
switch (this.size) {
case 0:
throw new Error("no such element");
case 1:
value = this.first.value;
this.first.value = this.first.next = this.first.prev = void 0;
this.first = void 0;
break;
case 2:
value = this.last.value;
this.last.prev = this.last.next = this.last.value = void 0;
this.last = void 0;
this.first.prev = this.first;
this.first.next = this.first;
break;
default:
const _last3 = this.last;
value = _last3.value;
this.last = this.getNode(this.size - 2);
this.last.next = this.first;
_last3.value = _last3.next = _last3.prev = void 0;
}
this.size--;
return value;
}
/**
* O(size / 2)<br>
* Ω(1)
* @param index
*/
getNode(index) {
if (index >= this.size || index < 0) throw new Error("no such element");
let node = this.first;
if (index > this.size / 2) {
node = this.last;
for (let i = this.size - 1; i > index; i--) {
node = node == null ? void 0 : node.prev;
}
} else {
for (let i = 0; i < index; i++) {
node = node == null ? void 0 : node.next;
}
}
return node;
}
/**
* For this method to work, a comparator must be set
* @param e
*/
includes(e) {
return this.indexOf(e) > -1;
}
/**
* For this method to work, a comparator must be set
* @param l
*/
equals(l) {
for (let i = 0; i < l.size; i++) {
if (this.comparator(l.get(i), this.get(i)) !== Ordering.EQ) {
return false;
}
}
return true;
}
indexOf(e) {
for (let i = 0; i < this.size; i++) {
if (this.comparator(e, this.get(i)) === Ordering.EQ) return i;
}
return -1;
}
sort(cmp) {
const backupCmp = this.comparator;
if (cmp) {
this.comparator = cmp;
}
const sorted = heapSort(this, this.comparator);
this.clear();
for (const sortedElement of sorted) {
this.add(sortedElement);
}
this.comparator = backupCmp;
}
/**
* In even cases: O(∑ i=1 to ⌊size÷2⌋ (i*2))<br>
* In odd cases: O((∑ i=1 to ⌊size÷2⌋ (i*2)) + ⌈size÷2⌉)<br>
* Ω(1)
*/
*reverseIterator() {
for (let i = this.size - 1; i >= 0; i--) {
yield this.getNode(i).value;
}
}
/**
* O(size)
*/
[Symbol.iterator]() {
let first = this.first;
let i = this.size - 1;
return {
next: () => {
return {
done: i === -1,
value: (() => {
if (first && i >= 0) {
const val = first.value;
first = first.next;
i--;
return val;
}
return void 0;
})()
};
}
};
}
}
function calculateCount(start, end, right = false) {
if (start === end) return 1;
if (right) {
if (start < end) {
return end - start + 1;
}
return this.size - start + end + 1;
}
if (start < end) {
return this.size - (end - start) + 1;
}
return start - end + 1;
}
function calculateStartAndEnd(startIndex, endIndex) {
let start, end;
if (startIndex < 0)
start = this.size + startIndex % this.size;
else
start = startIndex % this.size;
if (endIndex < 0)
end = this.size + endIndex % this.size;
else
end = endIndex % this.size;
return { start, end };
}
function _splice(startIndex, deleteCount, slice) {
if (deleteCount === 0) return slice;
const deleteC = deleteCount % this.size;
const size = this.size;
let start = startIndex < 0 ? this.size + (startIndex % this.size === 0 ? -this.size : startIndex % this.size) : startIndex % this.size;
if (deleteCount < 0) {
let toIndex2 = Math.abs(deleteCount);
if (deleteCount === -this.size || deleteCount < -this.size && deleteC === 0) {
toIndex2 = size;
}
for (let i = 0, j = start; i < toIndex2; i++, j--) {
if (j < 0) {
slice.add(this.remove(this.size - 1));
j = this.size;
} else {
slice.add(this.remove(j));
}
}
this.size -= slice.size;
slice.comparator = this.comparator;
return slice;
}
let toIndex = Math.abs(deleteC) + start;
if (deleteCount === this.size || deleteCount > this.size && deleteC === 0) {
toIndex = size + start;
}
for (let i = start; i < toIndex; i++) {
slice.add(this.remove(start % this.size));
if (this.size < start) {
start--;
}
}
return slice;
}
function _slice(startIndex, endIndex, slice) {
let { start, end } = calculateStartAndEnd.call(this, startIndex, endIndex);
const count = calculateCount.call(this, start, end, true);
let startNode = this.getNode(start);
for (let i = 0; i < count; i++) {
slice.add(startNode == null ? void 0 : startNode.value);
startNode = (startNode == null ? void 0 : startNode.next) || this.first;
start++;
}
return slice;
}
class FibonacciHeap {
constructor(comparator, elements) {
__publicField(this, "rootList");
__publicField(this, "minNode");
__publicField(this, "size", 0);
__publicField(this, "comparator");
__publicField(this, "goldenCut", (1 + Math.sqrt(5)) / 2);
this.comparator = comparator;
if (elements) {
for (const e of elements) {
this.insert(e);
}
}
}
/**
* O(1)
* @param e
*/
insert(e) {
if (e === void 0) return void 0;
const node = {
value: e,
degree: 0,
marked: false
};
node.left = node;
node.right = node;
if (!this.minNode) {
this.minNode = this.rootList = node;
} else {
this.mergeWithRootList(node);
if (this.comparator(node.value, this.minNode.value) === Ordering.LT) {
this.minNode = node;
}
}
this.size++;
return node;
}
add(e) {
return this.insert(e);
}
/**
* O(log(size)) (amortized)
*
* @param e
*/
delete(e) {
this.decreaseKey(e, null);
return this.extractMin();
}
/**
* Decreases a nodes key. When the newValue is null or undefined, node will get the new