data-structure-typed 2.4.4 → 2.4.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (41) hide show
  1. package/CHANGELOG.md +22 -1
  2. package/README.md +24 -1
  3. package/dist/cjs/index.cjs +459 -132
  4. package/dist/cjs-legacy/index.cjs +459 -130
  5. package/dist/esm/index.mjs +459 -133
  6. package/dist/esm-legacy/index.mjs +459 -131
  7. package/dist/types/common/error.d.ts +23 -0
  8. package/dist/types/common/index.d.ts +1 -0
  9. package/dist/types/data-structures/binary-tree/binary-tree.d.ts +10 -0
  10. package/dist/types/data-structures/binary-tree/red-black-tree.d.ts +7 -1
  11. package/dist/types/data-structures/graph/abstract-graph.d.ts +44 -0
  12. package/dist/types/data-structures/graph/directed-graph.d.ts +1 -0
  13. package/dist/types/data-structures/graph/undirected-graph.d.ts +14 -0
  14. package/dist/types/data-structures/queue/deque.d.ts +41 -1
  15. package/dist/types/types/data-structures/queue/deque.d.ts +6 -0
  16. package/dist/umd/data-structure-typed.js +458 -129
  17. package/dist/umd/data-structure-typed.min.js +4 -2
  18. package/package.json +2 -2
  19. package/src/common/error.ts +60 -0
  20. package/src/common/index.ts +2 -0
  21. package/src/data-structures/base/iterable-element-base.ts +3 -2
  22. package/src/data-structures/binary-tree/binary-indexed-tree.ts +6 -5
  23. package/src/data-structures/binary-tree/binary-tree.ts +113 -42
  24. package/src/data-structures/binary-tree/bst.ts +11 -3
  25. package/src/data-structures/binary-tree/red-black-tree.ts +20 -0
  26. package/src/data-structures/binary-tree/tree-map.ts +8 -7
  27. package/src/data-structures/binary-tree/tree-multi-map.ts +4 -4
  28. package/src/data-structures/binary-tree/tree-multi-set.ts +5 -4
  29. package/src/data-structures/binary-tree/tree-set.ts +7 -6
  30. package/src/data-structures/graph/abstract-graph.ts +106 -1
  31. package/src/data-structures/graph/directed-graph.ts +4 -0
  32. package/src/data-structures/graph/undirected-graph.ts +95 -0
  33. package/src/data-structures/hash/hash-map.ts +13 -2
  34. package/src/data-structures/heap/heap.ts +4 -3
  35. package/src/data-structures/heap/max-heap.ts +2 -3
  36. package/src/data-structures/matrix/matrix.ts +9 -10
  37. package/src/data-structures/priority-queue/max-priority-queue.ts +2 -3
  38. package/src/data-structures/queue/deque.ts +71 -3
  39. package/src/data-structures/trie/trie.ts +2 -1
  40. package/src/types/data-structures/queue/deque.ts +7 -0
  41. package/src/utils/utils.ts +4 -2
@@ -193,6 +193,54 @@ var _IterableEntryBase = class _IterableEntryBase {
193
193
  __name(_IterableEntryBase, "IterableEntryBase");
194
194
  var IterableEntryBase = _IterableEntryBase;
195
195
 
196
+ // src/common/error.ts
197
+ var ERR = {
198
+ // Range / index
199
+ indexOutOfRange: /* @__PURE__ */ __name((index, min, max, ctx) => `${ctx ? ctx + ": " : ""}Index ${index} is out of range [${min}, ${max}].`, "indexOutOfRange"),
200
+ invalidIndex: /* @__PURE__ */ __name((ctx) => `${ctx ? ctx + ": " : ""}Index must be an integer.`, "invalidIndex"),
201
+ // Type / argument
202
+ invalidArgument: /* @__PURE__ */ __name((reason, ctx) => `${ctx ? ctx + ": " : ""}${reason}`, "invalidArgument"),
203
+ comparatorRequired: /* @__PURE__ */ __name((ctx) => `${ctx ? ctx + ": " : ""}Comparator is required for non-number/non-string/non-Date keys.`, "comparatorRequired"),
204
+ invalidKey: /* @__PURE__ */ __name((reason, ctx) => `${ctx ? ctx + ": " : ""}${reason}`, "invalidKey"),
205
+ notAFunction: /* @__PURE__ */ __name((name, ctx) => `${ctx ? ctx + ": " : ""}${name} must be a function.`, "notAFunction"),
206
+ invalidEntry: /* @__PURE__ */ __name((ctx) => `${ctx ? ctx + ": " : ""}Each entry must be a [key, value] tuple.`, "invalidEntry"),
207
+ invalidNaN: /* @__PURE__ */ __name((ctx) => `${ctx ? ctx + ": " : ""}NaN is not a valid key.`, "invalidNaN"),
208
+ invalidDate: /* @__PURE__ */ __name((ctx) => `${ctx ? ctx + ": " : ""}Invalid Date key.`, "invalidDate"),
209
+ reduceEmpty: /* @__PURE__ */ __name((ctx) => `${ctx ? ctx + ": " : ""}Reduce of empty structure with no initial value.`, "reduceEmpty"),
210
+ callbackReturnType: /* @__PURE__ */ __name((expected, got, ctx) => `${ctx ? ctx + ": " : ""}Callback must return ${expected}; got ${got}.`, "callbackReturnType"),
211
+ // State / operation
212
+ invalidOperation: /* @__PURE__ */ __name((reason, ctx) => `${ctx ? ctx + ": " : ""}${reason}`, "invalidOperation"),
213
+ // Matrix
214
+ matrixDimensionMismatch: /* @__PURE__ */ __name((op) => `Matrix: Dimensions must be compatible for ${op}.`, "matrixDimensionMismatch"),
215
+ matrixSingular: /* @__PURE__ */ __name(() => "Matrix: Singular matrix, inverse does not exist.", "matrixSingular"),
216
+ matrixNotSquare: /* @__PURE__ */ __name(() => "Matrix: Must be square for inversion.", "matrixNotSquare"),
217
+ matrixNotRectangular: /* @__PURE__ */ __name(() => "Matrix: Must be rectangular for transposition.", "matrixNotRectangular"),
218
+ matrixRowMismatch: /* @__PURE__ */ __name((expected, got) => `Matrix: Expected row length ${expected}, but got ${got}.`, "matrixRowMismatch")
219
+ };
220
+
221
+ // src/common/index.ts
222
+ var DFSOperation = /* @__PURE__ */ ((DFSOperation2) => {
223
+ DFSOperation2[DFSOperation2["VISIT"] = 0] = "VISIT";
224
+ DFSOperation2[DFSOperation2["PROCESS"] = 1] = "PROCESS";
225
+ return DFSOperation2;
226
+ })(DFSOperation || {});
227
+ var _Range = class _Range {
228
+ constructor(low, high, includeLow = true, includeHigh = true) {
229
+ this.low = low;
230
+ this.high = high;
231
+ this.includeLow = includeLow;
232
+ this.includeHigh = includeHigh;
233
+ }
234
+ // Determine whether a key is within the range
235
+ isInRange(key, comparator) {
236
+ const lowCheck = this.includeLow ? comparator(key, this.low) >= 0 : comparator(key, this.low) > 0;
237
+ const highCheck = this.includeHigh ? comparator(key, this.high) <= 0 : comparator(key, this.high) < 0;
238
+ return lowCheck && highCheck;
239
+ }
240
+ };
241
+ __name(_Range, "Range");
242
+ var Range = _Range;
243
+
196
244
  // src/data-structures/base/iterable-element-base.ts
197
245
  var _IterableElementBase = class _IterableElementBase {
198
246
  /**
@@ -215,7 +263,7 @@ var _IterableElementBase = class _IterableElementBase {
215
263
  if (options) {
216
264
  const { toElementFn } = options;
217
265
  if (typeof toElementFn === "function") this._toElementFn = toElementFn;
218
- else if (toElementFn) throw new TypeError("toElementFn must be a function type");
266
+ else if (toElementFn) throw new TypeError(ERR.notAFunction("toElementFn"));
219
267
  }
220
268
  }
221
269
  /**
@@ -371,7 +419,7 @@ var _IterableElementBase = class _IterableElementBase {
371
419
  acc = initialValue;
372
420
  } else {
373
421
  const first = iter.next();
374
- if (first.done) throw new TypeError("Reduce of empty structure with no initial value");
422
+ if (first.done) throw new TypeError(ERR.reduceEmpty());
375
423
  acc = first.value;
376
424
  index = 1;
377
425
  }
@@ -441,8 +489,10 @@ var getMSB = /* @__PURE__ */ __name((value) => {
441
489
  }
442
490
  return 1 << 31 - Math.clz32(value);
443
491
  }, "getMSB");
444
- var rangeCheck = /* @__PURE__ */ __name((index, min, max, message = "Index out of bounds.") => {
445
- if (index < min || index > max) throw new RangeError(message);
492
+ var rangeCheck = /* @__PURE__ */ __name((index, min, max, message) => {
493
+ if (index < min || index > max) {
494
+ throw new RangeError(message != null ? message : `Index ${index} is out of range [${min}, ${max}].`);
495
+ }
446
496
  }, "rangeCheck");
447
497
  var throwRangeError = /* @__PURE__ */ __name((message = "The value is off-limits.") => {
448
498
  throw new RangeError(message);
@@ -814,8 +864,8 @@ var _LinkedHashMap = class _LinkedHashMap extends IterableEntryBase {
814
864
  if (this.isEntry(rawElement)) {
815
865
  return rawElement;
816
866
  }
817
- throw new Error(
818
- "If `entryOrRawElements` does not adhere to [key,value], provide `options.toEntryFn` to transform raw records."
867
+ throw new TypeError(
868
+ ERR.invalidArgument("If elements do not adhere to [key, value], provide options.toEntryFn to transform raw records.", "HashMap")
819
869
  );
820
870
  }, "_toEntryFn"));
821
871
  __publicField(this, "_size", 0);
@@ -1100,6 +1150,13 @@ var _LinkedHashMap = class _LinkedHashMap extends IterableEntryBase {
1100
1150
  }
1101
1151
  }
1102
1152
  _deleteNode(node) {
1153
+ const key = node.key;
1154
+ if (isWeakKey(key)) {
1155
+ this._objMap.delete(key);
1156
+ } else {
1157
+ const hash = this._hashFn(key);
1158
+ delete this._noObjMap[hash];
1159
+ }
1103
1160
  const { prev, next } = node;
1104
1161
  prev.next = next;
1105
1162
  next.prev = prev;
@@ -3607,17 +3664,16 @@ var LinkedListQueue = _LinkedListQueue;
3607
3664
 
3608
3665
  // src/data-structures/queue/deque.ts
3609
3666
  var _Deque = class _Deque extends LinearBase {
3610
- /**
3611
- * Create a Deque and optionally bulk-insert elements.
3612
- * @remarks Time O(N), Space O(N)
3613
- * @param [elements] - Iterable (or iterable-like) of elements/records to insert.
3614
- * @param [options] - Options such as bucketSize, toElementFn, and maxLen.
3615
- * @returns New Deque instance.
3616
- */
3617
3667
  constructor(elements = [], options) {
3618
3668
  super(options);
3619
3669
  __publicField(this, "_equals", /* @__PURE__ */ __name((a, b) => Object.is(a, b), "_equals"));
3620
3670
  __publicField(this, "_bucketSize", 1 << 12);
3671
+ __publicField(this, "_autoCompactRatio", 0.5);
3672
+ /**
3673
+ * Counter for shift/pop operations since last compaction check.
3674
+ * Only checks ratio every `_bucketSize` operations to minimize overhead.
3675
+ */
3676
+ __publicField(this, "_compactCounter", 0);
3621
3677
  __publicField(this, "_bucketFirst", 0);
3622
3678
  __publicField(this, "_firstInBucket", 0);
3623
3679
  __publicField(this, "_bucketLast", 0);
@@ -3626,8 +3682,9 @@ var _Deque = class _Deque extends LinearBase {
3626
3682
  __publicField(this, "_buckets", []);
3627
3683
  __publicField(this, "_length", 0);
3628
3684
  if (options) {
3629
- const { bucketSize } = options;
3685
+ const { bucketSize, autoCompactRatio } = options;
3630
3686
  if (typeof bucketSize === "number") this._bucketSize = bucketSize;
3687
+ if (typeof autoCompactRatio === "number") this._autoCompactRatio = autoCompactRatio;
3631
3688
  }
3632
3689
  let _size;
3633
3690
  if ("length" in elements) {
@@ -3652,6 +3709,24 @@ var _Deque = class _Deque extends LinearBase {
3652
3709
  get bucketSize() {
3653
3710
  return this._bucketSize;
3654
3711
  }
3712
+ /**
3713
+ * Get the auto-compaction ratio.
3714
+ * When `elements / (bucketCount * bucketSize)` drops below this ratio after
3715
+ * enough shift/pop operations, the deque auto-compacts.
3716
+ * @remarks Time O(1), Space O(1)
3717
+ * @returns Current ratio threshold. 0 means auto-compact is disabled.
3718
+ */
3719
+ get autoCompactRatio() {
3720
+ return this._autoCompactRatio;
3721
+ }
3722
+ /**
3723
+ * Set the auto-compaction ratio.
3724
+ * @remarks Time O(1), Space O(1)
3725
+ * @param value - Ratio in [0,1]. 0 disables auto-compact.
3726
+ */
3727
+ set autoCompactRatio(value) {
3728
+ this._autoCompactRatio = value;
3729
+ }
3655
3730
  /**
3656
3731
  * Get the index of the first bucket in use.
3657
3732
  * @remarks Time O(1), Space O(1)
@@ -3783,6 +3858,7 @@ var _Deque = class _Deque extends LinearBase {
3783
3858
  }
3784
3859
  }
3785
3860
  this._length -= 1;
3861
+ this._autoCompact();
3786
3862
  return element;
3787
3863
  }
3788
3864
  /**
@@ -3805,6 +3881,7 @@ var _Deque = class _Deque extends LinearBase {
3805
3881
  }
3806
3882
  }
3807
3883
  this._length -= 1;
3884
+ this._autoCompact();
3808
3885
  return element;
3809
3886
  }
3810
3887
  /**
@@ -4137,11 +4214,40 @@ var _Deque = class _Deque extends LinearBase {
4137
4214
  * @remarks Time O(N), Space O(1)
4138
4215
  * @returns void
4139
4216
  */
4217
+ /**
4218
+ * (Protected) Trigger auto-compaction if space utilization drops below threshold.
4219
+ * Only checks every `_bucketSize` operations to minimize hot-path overhead.
4220
+ * Uses element-based ratio: `elements / (bucketCount * bucketSize)`.
4221
+ */
4222
+ _autoCompact() {
4223
+ if (this._autoCompactRatio <= 0 || this._bucketCount <= 1) return;
4224
+ this._compactCounter++;
4225
+ if (this._compactCounter < this._bucketSize) return;
4226
+ this._compactCounter = 0;
4227
+ const utilization = this._length / (this._bucketCount * this._bucketSize);
4228
+ if (utilization < this._autoCompactRatio) {
4229
+ this.shrinkToFit();
4230
+ }
4231
+ }
4232
+ /**
4233
+ * Compact the deque by removing unused buckets.
4234
+ * @remarks Time O(N), Space O(1)
4235
+ * @returns True if compaction was performed (bucket count reduced).
4236
+ */
4237
+ /**
4238
+ * Compact the deque by removing unused buckets.
4239
+ * @remarks Time O(N), Space O(1)
4240
+ * @returns True if compaction was performed (bucket count reduced).
4241
+ */
4242
+ compact() {
4243
+ const before = this._bucketCount;
4244
+ this.shrinkToFit();
4245
+ return this._bucketCount < before;
4246
+ }
4140
4247
  shrinkToFit() {
4141
4248
  if (this._length === 0) return;
4142
4249
  const newBuckets = [];
4143
- if (this._bucketFirst === this._bucketLast) return;
4144
- else if (this._bucketFirst < this._bucketLast) {
4250
+ if (this._bucketFirst <= this._bucketLast) {
4145
4251
  for (let i = this._bucketFirst; i <= this._bucketLast; ++i) {
4146
4252
  newBuckets.push(this._buckets[i]);
4147
4253
  }
@@ -4156,6 +4262,8 @@ var _Deque = class _Deque extends LinearBase {
4156
4262
  this._bucketFirst = 0;
4157
4263
  this._bucketLast = newBuckets.length - 1;
4158
4264
  this._buckets = newBuckets;
4265
+ this._bucketCount = newBuckets.length;
4266
+ this._compactCounter = 0;
4159
4267
  }
4160
4268
  /**
4161
4269
  * Deep clone this deque, preserving options.
@@ -4353,7 +4461,7 @@ var _Heap = class _Heap extends IterableElementBase {
4353
4461
  __publicField(this, "_elements", []);
4354
4462
  __publicField(this, "_DEFAULT_COMPARATOR", /* @__PURE__ */ __name((a, b) => {
4355
4463
  if (typeof a === "object" || typeof b === "object") {
4356
- throw TypeError("When comparing object types, define a custom comparator in options.");
4464
+ throw new TypeError(ERR.comparatorRequired("Heap"));
4357
4465
  }
4358
4466
  if (a > b) return 1;
4359
4467
  if (a < b) return -1;
@@ -4663,7 +4771,7 @@ var _Heap = class _Heap extends IterableElementBase {
4663
4771
  */
4664
4772
  map(callback, options, thisArg) {
4665
4773
  const { comparator, toElementFn, ...rest } = options != null ? options : {};
4666
- if (!comparator) throw new TypeError("Heap.map requires options.comparator for EM");
4774
+ if (!comparator) throw new TypeError(ERR.comparatorRequired("Heap.map"));
4667
4775
  const out = this._createLike([], { ...rest, comparator, toElementFn });
4668
4776
  let i = 0;
4669
4777
  for (const x of this) {
@@ -4795,7 +4903,7 @@ var _FibonacciHeap = class _FibonacciHeap {
4795
4903
  __publicField(this, "_comparator");
4796
4904
  this.clear();
4797
4905
  this._comparator = comparator || this._defaultComparator;
4798
- if (typeof this.comparator !== "function") throw new Error("FibonacciHeap: comparator must be a function.");
4906
+ if (typeof this.comparator !== "function") throw new TypeError(ERR.notAFunction("comparator", "FibonacciHeap"));
4799
4907
  }
4800
4908
  /**
4801
4909
  * Get the circular root list head.
@@ -5006,9 +5114,7 @@ var _MaxHeap = class _MaxHeap extends Heap {
5006
5114
  super(elements, {
5007
5115
  comparator: /* @__PURE__ */ __name((a, b) => {
5008
5116
  if (typeof a === "object" || typeof b === "object") {
5009
- throw TypeError(
5010
- `When comparing object types, a custom comparator must be defined in the constructor's options parameter.`
5011
- );
5117
+ throw new TypeError(ERR.comparatorRequired("MaxHeap"));
5012
5118
  }
5013
5119
  if (a < b) return 1;
5014
5120
  if (a > b) return -1;
@@ -5173,7 +5279,7 @@ var _AbstractGraph = class _AbstractGraph extends IterableEntryBase {
5173
5279
  const newEdge = this.createEdge(srcOrEdge, dest, weight, value);
5174
5280
  return this._addEdge(newEdge);
5175
5281
  } else {
5176
- throw new Error("dest must be a Vertex or vertex key while srcOrEdge is an Edge");
5282
+ throw new TypeError(ERR.invalidArgument("dest must be a Vertex or vertex key when srcOrEdge is an Edge.", "Graph"));
5177
5283
  }
5178
5284
  }
5179
5285
  }
@@ -5857,6 +5963,94 @@ var _AbstractGraph = class _AbstractGraph extends IterableEntryBase {
5857
5963
  _getVertexKey(vertexOrKey) {
5858
5964
  return vertexOrKey instanceof AbstractVertex ? vertexOrKey.key : vertexOrKey;
5859
5965
  }
5966
+ /**
5967
+ * The edge connector string used in visual output.
5968
+ * Override in subclasses (e.g., '--' for undirected, '->' for directed).
5969
+ */
5970
+ get _edgeConnector() {
5971
+ return "--";
5972
+ }
5973
+ /**
5974
+ * Generate a text-based visual representation of the graph.
5975
+ *
5976
+ * **Adjacency list format:**
5977
+ * ```
5978
+ * Graph (5 vertices, 6 edges):
5979
+ * A -> B (1), C (2)
5980
+ * B -> D (3)
5981
+ * C -> (no outgoing edges)
5982
+ * D -> A (1)
5983
+ * E (isolated)
5984
+ * ```
5985
+ *
5986
+ * @param options - Optional display settings.
5987
+ * @param options.showWeight - Whether to show edge weights (default: true).
5988
+ * @returns The visual string.
5989
+ */
5990
+ toVisual(options) {
5991
+ var _a;
5992
+ const showWeight = (_a = options == null ? void 0 : options.showWeight) != null ? _a : true;
5993
+ const vertices = [...this._vertexMap.values()];
5994
+ const vertexCount = vertices.length;
5995
+ const edgeCount = this.edgeSet().length;
5996
+ const lines = [`Graph (${vertexCount} vertices, ${edgeCount} edges):`];
5997
+ for (const vertex of vertices) {
5998
+ const neighbors = this.getNeighbors(vertex);
5999
+ if (neighbors.length === 0) {
6000
+ lines.push(` ${vertex.key} (isolated)`);
6001
+ } else {
6002
+ const edgeStrs = neighbors.map((neighbor) => {
6003
+ const edge = this.getEdge(vertex, neighbor);
6004
+ if (edge && showWeight && edge.weight !== void 0 && edge.weight !== 1) {
6005
+ return `${neighbor.key} (${edge.weight})`;
6006
+ }
6007
+ return `${neighbor.key}`;
6008
+ });
6009
+ lines.push(` ${vertex.key} ${this._edgeConnector} ${edgeStrs.join(", ")}`);
6010
+ }
6011
+ }
6012
+ return lines.join("\n");
6013
+ }
6014
+ /**
6015
+ * Generate DOT language representation for Graphviz.
6016
+ *
6017
+ * @param options - Optional display settings.
6018
+ * @param options.name - Graph name (default: 'G').
6019
+ * @param options.showWeight - Whether to label edges with weight (default: true).
6020
+ * @returns DOT format string.
6021
+ */
6022
+ toDot(options) {
6023
+ var _a, _b;
6024
+ const name = (_a = options == null ? void 0 : options.name) != null ? _a : "G";
6025
+ const showWeight = (_b = options == null ? void 0 : options.showWeight) != null ? _b : true;
6026
+ const isDirected = this._edgeConnector === "->";
6027
+ const graphType = isDirected ? "digraph" : "graph";
6028
+ const edgeOp = isDirected ? "->" : "--";
6029
+ const lines = [`${graphType} ${name} {`];
6030
+ for (const vertex of this._vertexMap.values()) {
6031
+ lines.push(` "${vertex.key}";`);
6032
+ }
6033
+ const visited = /* @__PURE__ */ new Set();
6034
+ for (const vertex of this._vertexMap.values()) {
6035
+ for (const neighbor of this.getNeighbors(vertex)) {
6036
+ const edgeId = isDirected ? `${vertex.key}->${neighbor.key}` : [vertex.key, neighbor.key].sort().join("--");
6037
+ if (visited.has(edgeId)) continue;
6038
+ visited.add(edgeId);
6039
+ const edge = this.getEdge(vertex, neighbor);
6040
+ const label = edge && showWeight && edge.weight !== void 0 && edge.weight !== 1 ? ` [label="${edge.weight}"]` : "";
6041
+ lines.push(` "${vertex.key}" ${edgeOp} "${neighbor.key}"${label};`);
6042
+ }
6043
+ }
6044
+ lines.push("}");
6045
+ return lines.join("\n");
6046
+ }
6047
+ /**
6048
+ * Print the graph to console.
6049
+ * @param options - Display settings passed to `toVisual`.
6050
+ */
6051
+ print(options) {
6052
+ console.log(this.toVisual(options));
6053
+ }
5860
6054
  };
5861
6055
  __name(_AbstractGraph, "AbstractGraph");
5862
6056
  var AbstractGraph = _AbstractGraph;
@@ -5891,6 +6085,9 @@ var _DirectedGraph = class _DirectedGraph extends AbstractGraph {
5891
6085
  __publicField(this, "_outEdgeMap", /* @__PURE__ */ new Map());
5892
6086
  __publicField(this, "_inEdgeMap", /* @__PURE__ */ new Map());
5893
6087
  }
6088
+ get _edgeConnector() {
6089
+ return "->";
6090
+ }
5894
6091
  get outEdgeMap() {
5895
6092
  return this._outEdgeMap;
5896
6093
  }
@@ -6671,6 +6868,84 @@ var _UndirectedGraph = class _UndirectedGraph extends AbstractGraph {
6671
6868
  cutVertices
6672
6869
  };
6673
6870
  }
6871
+ /**
6872
+ * Find biconnected components using edge-stack Tarjan variant.
6873
+ * A biconnected component is a maximal biconnected subgraph.
6874
+ * @returns Array of edge arrays, each representing a biconnected component.
6875
+ * @remarks Time O(V + E), Space O(V + E)
6876
+ */
6877
+ getBiconnectedComponents() {
6878
+ const dfn = /* @__PURE__ */ new Map();
6879
+ const low = /* @__PURE__ */ new Map();
6880
+ const edgeStack = [];
6881
+ const components = [];
6882
+ let time = 0;
6883
+ const dfs = /* @__PURE__ */ __name((vertex, parent) => {
6884
+ dfn.set(vertex, time);
6885
+ low.set(vertex, time);
6886
+ time++;
6887
+ const neighbors = this.getNeighbors(vertex);
6888
+ let childCount = 0;
6889
+ for (const neighbor of neighbors) {
6890
+ const edge = this.getEdge(vertex, neighbor);
6891
+ if (!edge) continue;
6892
+ if (!dfn.has(neighbor)) {
6893
+ childCount++;
6894
+ edgeStack.push(edge);
6895
+ dfs(neighbor, vertex);
6896
+ low.set(vertex, Math.min(low.get(vertex), low.get(neighbor)));
6897
+ if (parent === void 0 && childCount > 1 || parent !== void 0 && low.get(neighbor) >= dfn.get(vertex)) {
6898
+ const component = [];
6899
+ let e;
6900
+ do {
6901
+ e = edgeStack.pop();
6902
+ if (e) component.push(e);
6903
+ } while (e && e !== edge);
6904
+ if (component.length > 0) components.push(component);
6905
+ }
6906
+ } else if (neighbor !== parent && dfn.get(neighbor) < dfn.get(vertex)) {
6907
+ edgeStack.push(edge);
6908
+ low.set(vertex, Math.min(low.get(vertex), dfn.get(neighbor)));
6909
+ }
6910
+ }
6911
+ }, "dfs");
6912
+ for (const vertex of this.vertexMap.values()) {
6913
+ if (!dfn.has(vertex)) {
6914
+ dfs(vertex, void 0);
6915
+ if (edgeStack.length > 0) {
6916
+ components.push([...edgeStack]);
6917
+ edgeStack.length = 0;
6918
+ }
6919
+ }
6920
+ }
6921
+ return components;
6922
+ }
6923
+ /**
6924
+ * Detect whether the graph contains a cycle.
6925
+ * Uses DFS with parent tracking.
6926
+ * @returns `true` if a cycle exists, `false` otherwise.
6927
+ * @remarks Time O(V + E), Space O(V)
6928
+ */
6929
+ hasCycle() {
6930
+ const visited = /* @__PURE__ */ new Set();
6931
+ const dfs = /* @__PURE__ */ __name((vertex, parent) => {
6932
+ visited.add(vertex);
6933
+ for (const neighbor of this.getNeighbors(vertex)) {
6934
+ if (!visited.has(neighbor)) {
6935
+ if (dfs(neighbor, vertex)) return true;
6936
+ } else if (neighbor !== parent) {
6937
+ return true;
6938
+ }
6939
+ }
6940
+ return false;
6941
+ }, "dfs");
6942
+ for (const vertex of this.vertexMap.values()) {
6943
+ if (!visited.has(vertex)) {
6944
+ if (dfs(vertex, void 0)) return true;
6945
+ }
6946
+ }
6947
+ return false;
6948
+ }
6674
6949
  /**
6675
6950
  * Get bridges discovered by `tarjan()`.
6676
6951
  * @returns Array of edges that are bridges.
@@ -6823,29 +7098,6 @@ var _MapGraph = class _MapGraph extends DirectedGraph {
6823
7098
  __name(_MapGraph, "MapGraph");
6824
7099
  var MapGraph = _MapGraph;
6825
7100
 
6826
- // src/common/index.ts
6827
- var DFSOperation = /* @__PURE__ */ ((DFSOperation2) => {
6828
- DFSOperation2[DFSOperation2["VISIT"] = 0] = "VISIT";
6829
- DFSOperation2[DFSOperation2["PROCESS"] = 1] = "PROCESS";
6830
- return DFSOperation2;
6831
- })(DFSOperation || {});
6832
- var _Range = class _Range {
6833
- constructor(low, high, includeLow = true, includeHigh = true) {
6834
- this.low = low;
6835
- this.high = high;
6836
- this.includeLow = includeLow;
6837
- this.includeHigh = includeHigh;
6838
- }
6839
- // Determine whether a key is within the range
6840
- isInRange(key, comparator) {
6841
- const lowCheck = this.includeLow ? comparator(key, this.low) >= 0 : comparator(key, this.low) > 0;
6842
- const highCheck = this.includeHigh ? comparator(key, this.high) <= 0 : comparator(key, this.high) < 0;
6843
- return lowCheck && highCheck;
6844
- }
6845
- };
6846
- __name(_Range, "Range");
6847
- var Range = _Range;
6848
-
6849
7101
  // src/data-structures/binary-tree/binary-tree.ts
6850
7102
  var _BinaryTreeNode = class _BinaryTreeNode {
6851
7103
  /**
@@ -7018,7 +7270,7 @@ var _BinaryTree = class _BinaryTree extends IterableEntryBase {
7018
7270
  if (isMapMode !== void 0) this._isMapMode = isMapMode;
7019
7271
  if (isDuplicate !== void 0) this._isDuplicate = isDuplicate;
7020
7272
  if (typeof toEntryFn === "function") this._toEntryFn = toEntryFn;
7021
- else if (toEntryFn) throw TypeError("toEntryFn must be a function type");
7273
+ else if (toEntryFn) throw new TypeError(ERR.notAFunction("toEntryFn", "BinaryTree"));
7022
7274
  }
7023
7275
  if (keysNodesEntriesOrRaws) this.setMany(keysNodesEntriesOrRaws);
7024
7276
  }
@@ -7246,7 +7498,7 @@ var _BinaryTree = class _BinaryTree extends IterableEntryBase {
7246
7498
  if (!this._root) {
7247
7499
  this._setRoot(newNode);
7248
7500
  if (this._isMapMode && newNode !== null && newNode !== void 0) this._store.set(newNode.key, newNode);
7249
- this._size = 1;
7501
+ if (newNode !== null) this._size = 1;
7250
7502
  return true;
7251
7503
  }
7252
7504
  const queue = new Queue([this._root]);
@@ -7278,7 +7530,7 @@ var _BinaryTree = class _BinaryTree extends IterableEntryBase {
7278
7530
  potentialParent.right = newNode;
7279
7531
  }
7280
7532
  if (this._isMapMode && newNode !== null && newNode !== void 0) this._store.set(newNode.key, newNode);
7281
- this._size++;
7533
+ if (newNode !== null) this._size++;
7282
7534
  return true;
7283
7535
  }
7284
7536
  return false;
@@ -7847,7 +8099,7 @@ var _BinaryTree = class _BinaryTree extends IterableEntryBase {
7847
8099
  }
7848
8100
  /**
7849
8101
  * Finds all leaf nodes in the tree.
7850
- * @remarks Time O(N), visits every node. Space O(H) for recursive stack or O(N) for iterative queue.
8102
+ * @remarks Time O(N), visits every node. Space O(H) for recursive or iterative stack.
7851
8103
  *
7852
8104
  * @template C - The type of the callback function.
7853
8105
  * @param [callback=this._DEFAULT_NODE_CALLBACK] - Function to call on each leaf node.
@@ -7870,15 +8122,15 @@ var _BinaryTree = class _BinaryTree extends IterableEntryBase {
7870
8122
  }, "dfs");
7871
8123
  dfs(startNode);
7872
8124
  } else {
7873
- const queue = new Queue([startNode]);
7874
- while (queue.length > 0) {
7875
- const cur = queue.shift();
8125
+ const stack = [startNode];
8126
+ while (stack.length > 0) {
8127
+ const cur = stack.pop();
7876
8128
  if (this.isRealNode(cur)) {
7877
8129
  if (this.isLeaf(cur)) {
7878
8130
  leaves.push(callback(cur));
7879
8131
  }
7880
- if (this.isRealNode(cur.left)) queue.push(cur.left);
7881
- if (this.isRealNode(cur.right)) queue.push(cur.right);
8132
+ if (this.isRealNode(cur.right)) stack.push(cur.right);
8133
+ if (this.isRealNode(cur.left)) stack.push(cur.left);
7882
8134
  }
7883
8135
  }
7884
8136
  }
@@ -8334,42 +8586,98 @@ var _BinaryTree = class _BinaryTree extends IterableEntryBase {
8334
8586
  _displayAux(node, options) {
8335
8587
  const { isShowNull, isShowUndefined, isShowRedBlackNIL } = options;
8336
8588
  const emptyDisplayLayout = [["\u2500"], 1, 0, 0];
8337
- if (node === null && !isShowNull) {
8338
- return emptyDisplayLayout;
8339
- } else if (node === void 0 && !isShowUndefined) {
8340
- return emptyDisplayLayout;
8341
- } else if (this.isNIL(node) && !isShowRedBlackNIL) {
8342
- return emptyDisplayLayout;
8343
- } else if (node !== null && node !== void 0) {
8344
- const key = node.key, line = this.isNIL(node) ? "S" : String(key), width = line.length;
8345
- return _buildNodeDisplay(
8346
- line,
8347
- width,
8348
- this._displayAux(node.left, options),
8349
- this._displayAux(node.right, options)
8350
- );
8351
- } else {
8352
- const line = node === void 0 ? "U" : "N", width = line.length;
8353
- return _buildNodeDisplay(line, width, [[""], 1, 0, 0], [[""], 1, 0, 0]);
8354
- }
8355
- function _buildNodeDisplay(line, width, left, right) {
8356
- const [leftLines, leftWidth, leftHeight, leftMiddle] = left;
8357
- const [rightLines, rightWidth, rightHeight, rightMiddle] = right;
8358
- const firstLine = " ".repeat(Math.max(0, leftMiddle + 1)) + "_".repeat(Math.max(0, leftWidth - leftMiddle - 1)) + line + "_".repeat(Math.max(0, rightMiddle)) + " ".repeat(Math.max(0, rightWidth - rightMiddle));
8359
- const secondLine = (leftHeight > 0 ? " ".repeat(leftMiddle) + "/" + " ".repeat(leftWidth - leftMiddle - 1) : " ".repeat(leftWidth)) + " ".repeat(width) + (rightHeight > 0 ? " ".repeat(rightMiddle) + "\\" + " ".repeat(rightWidth - rightMiddle - 1) : " ".repeat(rightWidth));
8360
- const mergedLines = [firstLine, secondLine];
8361
- for (let i = 0; i < Math.max(leftHeight, rightHeight); i++) {
8362
- const leftLine = i < leftHeight ? leftLines[i] : " ".repeat(leftWidth);
8363
- const rightLine = i < rightHeight ? rightLines[i] : " ".repeat(rightWidth);
8364
- mergedLines.push(leftLine + " ".repeat(width) + rightLine);
8589
+ const newFrame = /* @__PURE__ */ __name((n) => ({
8590
+ node: n,
8591
+ stage: 0,
8592
+ leftLayout: emptyDisplayLayout,
8593
+ rightLayout: emptyDisplayLayout
8594
+ }), "newFrame");
8595
+ const stack = [newFrame(node)];
8596
+ let result = emptyDisplayLayout;
8597
+ const setChildResult = /* @__PURE__ */ __name((layout) => {
8598
+ if (stack.length === 0) {
8599
+ result = layout;
8600
+ return;
8601
+ }
8602
+ const parent = stack[stack.length - 1];
8603
+ if (parent.stage === 1) parent.leftLayout = layout;
8604
+ else parent.rightLayout = layout;
8605
+ }, "setChildResult");
8606
+ while (stack.length > 0) {
8607
+ const frame = stack[stack.length - 1];
8608
+ const cur = frame.node;
8609
+ if (frame.stage === 0) {
8610
+ if (this._isDisplayLeaf(cur, options)) {
8611
+ stack.pop();
8612
+ const layout = this._resolveDisplayLeaf(cur, options, emptyDisplayLayout);
8613
+ setChildResult(layout);
8614
+ continue;
8615
+ }
8616
+ frame.stage = 1;
8617
+ stack.push(newFrame(cur.left));
8618
+ } else if (frame.stage === 1) {
8619
+ frame.stage = 2;
8620
+ stack.push(newFrame(cur.right));
8621
+ } else {
8622
+ stack.pop();
8623
+ const line = this.isNIL(cur) ? "S" : String(cur.key);
8624
+ const layout = _BinaryTree._buildNodeDisplay(line, line.length, frame.leftLayout, frame.rightLayout);
8625
+ setChildResult(layout);
8365
8626
  }
8366
- return [
8367
- mergedLines,
8368
- leftWidth + width + rightWidth,
8369
- Math.max(leftHeight, rightHeight) + 2,
8370
- leftWidth + Math.floor(width / 2)
8371
- ];
8372
8627
  }
8628
+ return result;
8629
+ }
8630
+ static _buildNodeDisplay(line, width, left, right) {
8631
+ const [leftLines, leftWidth, leftHeight, leftMiddle] = left;
8632
+ const [rightLines, rightWidth, rightHeight, rightMiddle] = right;
8633
+ const firstLine = " ".repeat(Math.max(0, leftMiddle + 1)) + "_".repeat(Math.max(0, leftWidth - leftMiddle - 1)) + line + "_".repeat(Math.max(0, rightMiddle)) + " ".repeat(Math.max(0, rightWidth - rightMiddle));
8634
+ const secondLine = (leftHeight > 0 ? " ".repeat(leftMiddle) + "/" + " ".repeat(leftWidth - leftMiddle - 1) : " ".repeat(leftWidth)) + " ".repeat(width) + (rightHeight > 0 ? " ".repeat(rightMiddle) + "\\" + " ".repeat(rightWidth - rightMiddle - 1) : " ".repeat(rightWidth));
8635
+ const mergedLines = [firstLine, secondLine];
8636
+ for (let i = 0; i < Math.max(leftHeight, rightHeight); i++) {
8637
+ const leftLine = i < leftHeight ? leftLines[i] : " ".repeat(leftWidth);
8638
+ const rightLine = i < rightHeight ? rightLines[i] : " ".repeat(rightWidth);
8639
+ mergedLines.push(leftLine + " ".repeat(width) + rightLine);
8640
+ }
8641
+ return [
8642
+ mergedLines,
8643
+ leftWidth + width + rightWidth,
8644
+ Math.max(leftHeight, rightHeight) + 2,
8645
+ leftWidth + Math.floor(width / 2)
8646
+ ];
8647
+ }
8648
+ /**
8649
+ * Check if a node is a display leaf (empty, null, undefined, NIL, or real leaf).
8650
+ */
8651
+ _isDisplayLeaf(node, options) {
8652
+ const { isShowNull, isShowUndefined, isShowRedBlackNIL } = options;
8653
+ if (node === null && !isShowNull) return true;
8654
+ if (node === void 0 && !isShowUndefined) return true;
8655
+ if (this.isNIL(node) && !isShowRedBlackNIL) return true;
8656
+ if (node === null || node === void 0) return true;
8657
+ const hasDisplayableLeft = this._hasDisplayableChild(node.left, options);
8658
+ const hasDisplayableRight = this._hasDisplayableChild(node.right, options);
8659
+ return !hasDisplayableLeft && !hasDisplayableRight;
8660
+ }
8661
+ _hasDisplayableChild(child, options) {
8662
+ if (child === null) return !!options.isShowNull;
8663
+ if (child === void 0) return !!options.isShowUndefined;
8664
+ if (this.isNIL(child)) return !!options.isShowRedBlackNIL;
8665
+ return true;
8666
+ }
8667
+ /**
8668
+ * Resolve a display leaf node to its layout.
8669
+ */
8670
+ _resolveDisplayLeaf(node, options, emptyDisplayLayout) {
8671
+ const { isShowNull, isShowUndefined, isShowRedBlackNIL } = options;
8672
+ if (node === null && !isShowNull) return emptyDisplayLayout;
8673
+ if (node === void 0 && !isShowUndefined) return emptyDisplayLayout;
8674
+ if (this.isNIL(node) && !isShowRedBlackNIL) return emptyDisplayLayout;
8675
+ if (node !== null && node !== void 0) {
8676
+ const line2 = this.isNIL(node) ? "S" : String(node.key);
8677
+ return _BinaryTree._buildNodeDisplay(line2, line2.length, emptyDisplayLayout, emptyDisplayLayout);
8678
+ }
8679
+ const line = node === void 0 ? "U" : "N";
8680
+ return _BinaryTree._buildNodeDisplay(line, line.length, [[""], 1, 0, 0], [[""], 1, 0, 0]);
8373
8681
  }
8374
8682
  /**
8375
8683
  * (Protected) Swaps the key/value properties of two nodes.
@@ -9375,9 +9683,15 @@ var _BST = class _BST extends BinaryTree {
9375
9683
  if (a < b) return -1;
9376
9684
  return 0;
9377
9685
  }
9686
+ if (a instanceof Date && b instanceof Date) {
9687
+ const ta = a.getTime();
9688
+ const tb = b.getTime();
9689
+ if (Number.isNaN(ta) || Number.isNaN(tb)) throw new TypeError(ERR.invalidDate("BST"));
9690
+ return ta > tb ? 1 : ta < tb ? -1 : 0;
9691
+ }
9378
9692
  if (typeof a === "object" || typeof b === "object") {
9379
- throw TypeError(
9380
- `When comparing object type keys, a custom comparator must be provided in the constructor's options!`
9693
+ throw new TypeError(
9694
+ ERR.comparatorRequired("BST")
9381
9695
  );
9382
9696
  }
9383
9697
  return 0;
@@ -9891,7 +10205,7 @@ var _BinaryIndexedTree = class _BinaryIndexedTree {
9891
10205
  */
9892
10206
  read(count) {
9893
10207
  if (!Number.isInteger(count)) {
9894
- throw new Error("Invalid count");
10208
+ throw new Error(ERR.invalidArgument("count must be an integer", "BinaryIndexedTree"));
9895
10209
  }
9896
10210
  return this._read(Math.max(Math.min(count, this.max), 0));
9897
10211
  }
@@ -9903,7 +10217,7 @@ var _BinaryIndexedTree = class _BinaryIndexedTree {
9903
10217
  */
9904
10218
  lowerBound(sum) {
9905
10219
  if (this.negativeCount > 0) {
9906
- throw new Error("Sequence is not non-descending");
10220
+ throw new Error(ERR.invalidOperation("Sequence is not non-descending.", "BinaryIndexedTree"));
9907
10221
  }
9908
10222
  return this._binarySearch(sum, (x, y) => x < y);
9909
10223
  }
@@ -9916,7 +10230,7 @@ var _BinaryIndexedTree = class _BinaryIndexedTree {
9916
10230
  */
9917
10231
  upperBound(sum) {
9918
10232
  if (this.negativeCount > 0) {
9919
- throw new Error("Must not be descending");
10233
+ throw new Error(ERR.invalidOperation("Sequence must not be descending.", "BinaryIndexedTree"));
9920
10234
  }
9921
10235
  return this._binarySearch(sum, (x, y) => x <= y);
9922
10236
  }
@@ -9967,10 +10281,10 @@ var _BinaryIndexedTree = class _BinaryIndexedTree {
9967
10281
  */
9968
10282
  _checkIndex(index) {
9969
10283
  if (!Number.isInteger(index)) {
9970
- throw new Error("Invalid index: Index must be an integer.");
10284
+ throw new TypeError(ERR.invalidIndex("BinaryIndexedTree"));
9971
10285
  }
9972
10286
  if (index < 0 || index >= this.max) {
9973
- throw new Error("Index out of range: Index must be within the range [0, this.max).");
10287
+ throw new RangeError(ERR.indexOutOfRange(index, 0, this.max - 1, "BinaryIndexedTree"));
9974
10288
  }
9975
10289
  }
9976
10290
  /**
@@ -11559,6 +11873,24 @@ var _RedBlackTree = class _RedBlackTree extends BST {
11559
11873
  * @param [thisArg] - See parameter type for details.
11560
11874
  * @returns A new RedBlackTree with mapped entries.
11561
11875
  */
11876
+ /**
11877
+ * Red-Black trees are self-balancing — `perfectlyBalance` rebuilds via
11878
+ * sorted bulk insert, which naturally produces a balanced RBT.
11879
+ * @remarks Time O(N), Space O(N)
11880
+ */
11881
+ perfectlyBalance(iterationType) {
11882
+ const entries = [];
11883
+ for (const [key, value] of this) entries.push([key, value]);
11884
+ if (entries.length <= 1) return true;
11885
+ this.clear();
11886
+ this.setMany(
11887
+ entries.map(([k]) => k),
11888
+ entries.map(([, v]) => v),
11889
+ true
11890
+ // isBalanceAdd
11891
+ );
11892
+ return true;
11893
+ }
11562
11894
  map(callback, options, thisArg) {
11563
11895
  const out = this._createLike([], options);
11564
11896
  let index = 0;
@@ -11883,7 +12215,7 @@ var _TreeSet = class _TreeSet {
11883
12215
  static createDefaultComparator() {
11884
12216
  return (a, b) => {
11885
12217
  if (typeof a === "number" && typeof b === "number") {
11886
- if (Number.isNaN(a) || Number.isNaN(b)) throw new TypeError("TreeSet: NaN is not a valid key");
12218
+ if (Number.isNaN(a) || Number.isNaN(b)) throw new TypeError(ERR.invalidNaN("TreeSet"));
11887
12219
  const aa = Object.is(a, -0) ? 0 : a;
11888
12220
  const bb = Object.is(b, -0) ? 0 : b;
11889
12221
  return aa > bb ? 1 : aa < bb ? -1 : 0;
@@ -11894,10 +12226,10 @@ var _TreeSet = class _TreeSet {
11894
12226
  if (a instanceof Date && b instanceof Date) {
11895
12227
  const ta = a.getTime();
11896
12228
  const tb = b.getTime();
11897
- if (Number.isNaN(ta) || Number.isNaN(tb)) throw new TypeError("TreeSet: invalid Date key");
12229
+ if (Number.isNaN(ta) || Number.isNaN(tb)) throw new TypeError(ERR.invalidDate("TreeSet"));
11898
12230
  return ta > tb ? 1 : ta < tb ? -1 : 0;
11899
12231
  }
11900
- throw new TypeError("TreeSet: comparator is required for non-number/non-string/non-Date keys");
12232
+ throw new TypeError(ERR.comparatorRequired("TreeSet"));
11901
12233
  };
11902
12234
  }
11903
12235
  /**
@@ -11915,15 +12247,15 @@ var _TreeSet = class _TreeSet {
11915
12247
  _validateKey(key) {
11916
12248
  if (!__privateGet(this, _isDefaultComparator)) return;
11917
12249
  if (typeof key === "number") {
11918
- if (Number.isNaN(key)) throw new TypeError("TreeSet: NaN is not a valid key");
12250
+ if (Number.isNaN(key)) throw new TypeError(ERR.invalidNaN("TreeSet"));
11919
12251
  return;
11920
12252
  }
11921
12253
  if (typeof key === "string") return;
11922
12254
  if (key instanceof Date) {
11923
- if (Number.isNaN(key.getTime())) throw new TypeError("TreeSet: invalid Date key");
12255
+ if (Number.isNaN(key.getTime())) throw new TypeError(ERR.invalidDate("TreeSet"));
11924
12256
  return;
11925
12257
  }
11926
- throw new TypeError("TreeSet: comparator is required for non-number/non-string/non-Date keys");
12258
+ throw new TypeError(ERR.comparatorRequired("TreeSet"));
11927
12259
  }
11928
12260
  /**
11929
12261
  * Add a key to the set (no-op if already present).
@@ -12246,15 +12578,15 @@ var _TreeMultiMap = class _TreeMultiMap {
12246
12578
  _validateKey(key) {
12247
12579
  if (!__privateGet(this, _isDefaultComparator2)) return;
12248
12580
  if (typeof key === "number") {
12249
- if (Number.isNaN(key)) throw new TypeError("TreeMultiMap: NaN is not a valid key");
12581
+ if (Number.isNaN(key)) throw new TypeError(ERR.invalidNaN("TreeMultiMap"));
12250
12582
  return;
12251
12583
  }
12252
12584
  if (typeof key === "string") return;
12253
12585
  if (key instanceof Date) {
12254
- if (Number.isNaN(key.getTime())) throw new TypeError("TreeMultiMap: invalid Date key");
12586
+ if (Number.isNaN(key.getTime())) throw new TypeError(ERR.invalidDate("TreeMultiMap"));
12255
12587
  return;
12256
12588
  }
12257
- throw new TypeError("TreeMultiMap: comparator is required for non-number/non-string/non-Date keys");
12589
+ throw new TypeError(ERR.comparatorRequired("TreeMultiMap"));
12258
12590
  }
12259
12591
  /**
12260
12592
  * Number of distinct keys.
@@ -12679,7 +13011,7 @@ var _TreeMap = class _TreeMap {
12679
13011
  [k, v] = toEntryFn(item);
12680
13012
  } else {
12681
13013
  if (!Array.isArray(item) || item.length < 2) {
12682
- throw new TypeError("TreeMap: each entry must be a [key, value] tuple");
13014
+ throw new TypeError(ERR.invalidEntry("TreeMap"));
12683
13015
  }
12684
13016
  k = item[0];
12685
13017
  v = item[1];
@@ -12700,7 +13032,7 @@ var _TreeMap = class _TreeMap {
12700
13032
  static createDefaultComparator() {
12701
13033
  return (a, b) => {
12702
13034
  if (typeof a === "number" && typeof b === "number") {
12703
- if (Number.isNaN(a) || Number.isNaN(b)) throw new TypeError("TreeMap: NaN is not a valid key");
13035
+ if (Number.isNaN(a) || Number.isNaN(b)) throw new TypeError(ERR.invalidNaN("TreeMap"));
12704
13036
  const aa = Object.is(a, -0) ? 0 : a;
12705
13037
  const bb = Object.is(b, -0) ? 0 : b;
12706
13038
  return aa > bb ? 1 : aa < bb ? -1 : 0;
@@ -12711,24 +13043,24 @@ var _TreeMap = class _TreeMap {
12711
13043
  if (a instanceof Date && b instanceof Date) {
12712
13044
  const ta = a.getTime();
12713
13045
  const tb = b.getTime();
12714
- if (Number.isNaN(ta) || Number.isNaN(tb)) throw new TypeError("TreeMap: invalid Date key");
13046
+ if (Number.isNaN(ta) || Number.isNaN(tb)) throw new TypeError(ERR.invalidDate("TreeMap"));
12715
13047
  return ta > tb ? 1 : ta < tb ? -1 : 0;
12716
13048
  }
12717
- throw new TypeError("TreeMap: comparator is required for non-number/non-string/non-Date keys");
13049
+ throw new TypeError(ERR.comparatorRequired("TreeMap"));
12718
13050
  };
12719
13051
  }
12720
13052
  _validateKey(key) {
12721
13053
  if (!__privateGet(this, _isDefaultComparator3)) return;
12722
13054
  if (typeof key === "number") {
12723
- if (Number.isNaN(key)) throw new TypeError("TreeMap: NaN is not a valid key");
13055
+ if (Number.isNaN(key)) throw new TypeError(ERR.invalidNaN("TreeMap"));
12724
13056
  return;
12725
13057
  }
12726
13058
  if (typeof key === "string") return;
12727
13059
  if (key instanceof Date) {
12728
- if (Number.isNaN(key.getTime())) throw new TypeError("TreeMap: invalid Date key");
13060
+ if (Number.isNaN(key.getTime())) throw new TypeError(ERR.invalidDate("TreeMap"));
12729
13061
  return;
12730
13062
  }
12731
- throw new TypeError("TreeMap: comparator is required for non-number/non-string/non-Date keys");
13063
+ throw new TypeError(ERR.comparatorRequired("TreeMap"));
12732
13064
  }
12733
13065
  /**
12734
13066
  * Number of entries in the map.
@@ -13057,22 +13389,22 @@ var _TreeMultiSet = class _TreeMultiSet {
13057
13389
  _validateKey(key) {
13058
13390
  if (!__privateGet(this, _isDefaultComparator4)) return;
13059
13391
  if (typeof key === "number") {
13060
- if (Number.isNaN(key)) throw new TypeError("TreeMultiSet: NaN is not a valid key");
13392
+ if (Number.isNaN(key)) throw new TypeError(ERR.invalidNaN("TreeMultiSet"));
13061
13393
  return;
13062
13394
  }
13063
13395
  if (typeof key === "string") return;
13064
13396
  if (key instanceof Date) {
13065
- if (Number.isNaN(key.getTime())) throw new TypeError("TreeMultiSet: invalid Date key");
13397
+ if (Number.isNaN(key.getTime())) throw new TypeError(ERR.invalidDate("TreeMultiSet"));
13066
13398
  return;
13067
13399
  }
13068
- throw new TypeError("TreeMultiSet: comparator is required for non-number/non-string/non-Date keys");
13400
+ throw new TypeError(ERR.comparatorRequired("TreeMultiSet"));
13069
13401
  }
13070
13402
  /**
13071
13403
  * Validates that count is a non-negative safe integer.
13072
13404
  * @remarks Time O(1), Space O(1)
13073
13405
  */
13074
13406
  _validateCount(n) {
13075
- if (!Number.isSafeInteger(n) || n < 0) throw new RangeError("TreeMultiSet: count must be a safe integer >= 0");
13407
+ if (!Number.isSafeInteger(n) || n < 0) throw new RangeError(ERR.invalidArgument("count must be a safe integer >= 0.", "TreeMultiSet"));
13076
13408
  }
13077
13409
  /**
13078
13410
  * Total occurrences (sumCounts).
@@ -13500,9 +13832,7 @@ var _MaxPriorityQueue = class _MaxPriorityQueue extends PriorityQueue {
13500
13832
  super(elements, {
13501
13833
  comparator: /* @__PURE__ */ __name((a, b) => {
13502
13834
  if (typeof a === "object" || typeof b === "object") {
13503
- throw TypeError(
13504
- `When comparing object types, a custom comparator must be defined in the constructor's options parameter.`
13505
- );
13835
+ throw new TypeError(ERR.comparatorRequired("MaxPriorityQueue"));
13506
13836
  }
13507
13837
  if (a < b) return 1;
13508
13838
  if (a > b) return -1;
@@ -13643,7 +13973,7 @@ var _Matrix = class _Matrix {
13643
13973
  */
13644
13974
  add(matrix) {
13645
13975
  if (!this.isMatchForCalculate(matrix)) {
13646
- throw new Error("Matrix dimensions must match for addition.");
13976
+ throw new Error(ERR.matrixDimensionMismatch("addition"));
13647
13977
  }
13648
13978
  const resultData = [];
13649
13979
  for (let i = 0; i < this.rows; i++) {
@@ -13675,7 +14005,7 @@ var _Matrix = class _Matrix {
13675
14005
  */
13676
14006
  subtract(matrix) {
13677
14007
  if (!this.isMatchForCalculate(matrix)) {
13678
- throw new Error("Matrix dimensions must match for subtraction.");
14008
+ throw new Error(ERR.matrixDimensionMismatch("subtraction"));
13679
14009
  }
13680
14010
  const resultData = [];
13681
14011
  for (let i = 0; i < this.rows; i++) {
@@ -13706,7 +14036,7 @@ var _Matrix = class _Matrix {
13706
14036
  */
13707
14037
  multiply(matrix) {
13708
14038
  if (this.cols !== matrix.rows) {
13709
- throw new Error("Matrix dimensions must be compatible for multiplication (A.cols = B.rows).");
14039
+ throw new Error(ERR.matrixDimensionMismatch("multiplication (A.cols must equal B.rows)"));
13710
14040
  }
13711
14041
  const resultData = [];
13712
14042
  for (let i = 0; i < this.rows; i++) {
@@ -13740,7 +14070,7 @@ var _Matrix = class _Matrix {
13740
14070
  */
13741
14071
  transpose() {
13742
14072
  if (this.data.some((row) => row.length !== this.rows)) {
13743
- throw new Error("Matrix must be rectangular for transposition.");
14073
+ throw new Error(ERR.matrixNotRectangular());
13744
14074
  }
13745
14075
  const resultData = [];
13746
14076
  for (let j = 0; j < this.cols; j++) {
@@ -13765,7 +14095,7 @@ var _Matrix = class _Matrix {
13765
14095
  inverse() {
13766
14096
  var _a;
13767
14097
  if (this.rows !== this.cols) {
13768
- throw new Error("Matrix must be square for inversion.");
14098
+ throw new Error(ERR.matrixNotSquare());
13769
14099
  }
13770
14100
  const augmentedMatrixData = [];
13771
14101
  for (let i = 0; i < this.rows; i++) {
@@ -13787,12 +14117,12 @@ var _Matrix = class _Matrix {
13787
14117
  pivotRow++;
13788
14118
  }
13789
14119
  if (pivotRow === this.rows) {
13790
- throw new Error("Matrix is singular, and its inverse does not exist.");
14120
+ throw new Error(ERR.matrixSingular());
13791
14121
  }
13792
14122
  augmentedMatrix._swapRows(i, pivotRow);
13793
14123
  const pivotElement = (_a = augmentedMatrix.get(i, i)) != null ? _a : 1;
13794
14124
  if (pivotElement === 0) {
13795
- throw new Error("Matrix is singular, and its inverse does not exist (division by zero).");
14125
+ throw new Error(ERR.matrixSingular());
13796
14126
  }
13797
14127
  augmentedMatrix._scaleRow(i, 1 / pivotElement);
13798
14128
  for (let j = 0; j < this.rows; j++) {
@@ -13822,9 +14152,7 @@ var _Matrix = class _Matrix {
13822
14152
  */
13823
14153
  dot(matrix) {
13824
14154
  if (this.cols !== matrix.rows) {
13825
- throw new Error(
13826
- "Number of columns in the first matrix must be equal to the number of rows in the second matrix for dot product."
13827
- );
14155
+ throw new Error(ERR.matrixDimensionMismatch("dot product (A.cols must equal B.rows)"));
13828
14156
  }
13829
14157
  const resultData = [];
13830
14158
  for (let i = 0; i < this.rows; i++) {
@@ -14446,7 +14774,7 @@ var _Trie = class _Trie extends IterableElementBase {
14446
14774
  for (const x of this) {
14447
14775
  const v = thisArg === void 0 ? callback(x, i++, this) : callback.call(thisArg, x, i++, this);
14448
14776
  if (typeof v !== "string") {
14449
- throw new TypeError(`Trie.map callback must return string; got ${typeof v}`);
14777
+ throw new TypeError(ERR.callbackReturnType("string", typeof v, "Trie.map"));
14450
14778
  }
14451
14779
  newTrie.add(v);
14452
14780
  }
@@ -14697,6 +15025,7 @@ exports.DirectedGraph = DirectedGraph;
14697
15025
  exports.DirectedVertex = DirectedVertex;
14698
15026
  exports.DoublyLinkedList = DoublyLinkedList;
14699
15027
  exports.DoublyLinkedListNode = DoublyLinkedListNode;
15028
+ exports.ERR = ERR;
14700
15029
  exports.FibonacciHeap = FibonacciHeap;
14701
15030
  exports.FibonacciHeapNode = FibonacciHeapNode;
14702
15031
  exports.HashMap = HashMap;