queue-typed
Advanced tools
Comparing version 2.0.0 to 2.0.1
@@ -253,3 +253,3 @@ "use strict"; | ||
const allPaths = this.getAllPathsBetween(v1, v2); | ||
let min = Infinity; | ||
let min = Number.MAX_SAFE_INTEGER; | ||
for (const path of allPaths) { | ||
@@ -319,3 +319,3 @@ min = Math.min(this.getPathSumWeight(path), min); | ||
const allPaths = this.getAllPathsBetween(v1, v2, 10000); | ||
let min = Infinity; | ||
let min = Number.MAX_SAFE_INTEGER; | ||
let minIndex = -1; | ||
@@ -384,3 +384,3 @@ let index = 0; | ||
dijkstraWithoutHeap(src, dest = undefined, getMinDist = false, genPaths = false) { | ||
let minDist = Infinity; | ||
let minDist = Number.MAX_SAFE_INTEGER; | ||
let minDest = undefined; | ||
@@ -401,3 +401,3 @@ let minPath = []; | ||
if (vertexOrKey instanceof AbstractVertex) | ||
distMap.set(vertexOrKey, Infinity); | ||
distMap.set(vertexOrKey, Number.MAX_SAFE_INTEGER); | ||
} | ||
@@ -407,3 +407,3 @@ distMap.set(srcVertex, 0); | ||
const getMinOfNoSeen = () => { | ||
let min = Infinity; | ||
let min = Number.MAX_SAFE_INTEGER; | ||
let minV = undefined; | ||
@@ -443,3 +443,3 @@ for (const [key, value] of distMap) { | ||
if (getMinDist) { | ||
minDist = distMap.get(destVertex) || Infinity; | ||
minDist = distMap.get(destVertex) || Number.MAX_SAFE_INTEGER; | ||
} | ||
@@ -506,3 +506,3 @@ if (genPaths) { | ||
var _a; | ||
let minDist = Infinity; | ||
let minDist = Number.MAX_SAFE_INTEGER; | ||
let minDest = undefined; | ||
@@ -522,3 +522,3 @@ let minPath = []; | ||
if (vertexOrKey instanceof AbstractVertex) | ||
distMap.set(vertexOrKey, Infinity); | ||
distMap.set(vertexOrKey, Number.MAX_SAFE_INTEGER); | ||
} | ||
@@ -560,3 +560,3 @@ const heap = new heap_1.Heap([], { comparator: (a, b) => a.key - b.key }); | ||
if (getMinDist) { | ||
minDist = distMap.get(destVertex) || Infinity; | ||
minDist = distMap.get(destVertex) || Number.MAX_SAFE_INTEGER; | ||
} | ||
@@ -630,3 +630,3 @@ if (genPaths) { | ||
const preMap = new Map(); // predecessor | ||
let min = Infinity; | ||
let min = Number.MAX_SAFE_INTEGER; | ||
let minPath = []; | ||
@@ -644,3 +644,3 @@ // TODO | ||
this._vertexMap.forEach(vertex => { | ||
distMap.set(vertex, Infinity); | ||
distMap.set(vertex, Number.MAX_SAFE_INTEGER); | ||
}); | ||
@@ -657,3 +657,3 @@ distMap.set(srcVertex, 0); | ||
if (sWeight !== undefined && dWeight !== undefined) { | ||
if (distMap.get(s) !== Infinity && sWeight + weight < dWeight) { | ||
if (distMap.get(s) !== Number.MAX_SAFE_INTEGER && sWeight + weight < dWeight) { | ||
distMap.set(d, sWeight + weight); | ||
@@ -703,3 +703,3 @@ if (genPath) | ||
if (sWeight) { | ||
if (sWeight !== Infinity && sWeight + weight < sWeight) | ||
if (sWeight !== Number.MAX_SAFE_INTEGER && sWeight + weight < sWeight) | ||
hasNegativeCycle = true; | ||
@@ -754,3 +754,3 @@ } | ||
for (let j = 0; j < n; j++) { | ||
costs[i][j] = ((_a = this.getEdge(idAndVertices[i][1], idAndVertices[j][1])) === null || _a === void 0 ? void 0 : _a.weight) || Infinity; | ||
costs[i][j] = ((_a = this.getEdge(idAndVertices[i][1], idAndVertices[j][1])) === null || _a === void 0 ? void 0 : _a.weight) || Number.MAX_SAFE_INTEGER; | ||
} | ||
@@ -757,0 +757,0 @@ } |
@@ -16,2 +16,48 @@ /** | ||
* 4. Unordered Collection: HashMap does not guarantee the order of entries, and the order may change over time. | ||
* @example | ||
* // should maintain insertion order | ||
* const linkedHashMap = new LinkedHashMap<number, string>(); | ||
* linkedHashMap.set(1, 'A'); | ||
* linkedHashMap.set(2, 'B'); | ||
* linkedHashMap.set(3, 'C'); | ||
* | ||
* const result = Array.from(linkedHashMap); | ||
* console.log(result); // [ | ||
* // [1, 'A'], | ||
* // [2, 'B'], | ||
* // [3, 'C'] | ||
* // ] | ||
* @example | ||
* // fast lookup of values by key | ||
* const hashMap = new HashMap<number, string>(); | ||
* hashMap.set(1, 'A'); | ||
* hashMap.set(2, 'B'); | ||
* hashMap.set(3, 'C'); | ||
* | ||
* console.log(hashMap.get(1)); // 'A' | ||
* console.log(hashMap.get(2)); // 'B' | ||
* console.log(hashMap.get(3)); // 'C' | ||
* console.log(hashMap.get(99)); // undefined | ||
* @example | ||
* // remove duplicates when adding multiple entries | ||
* const hashMap = new HashMap<number, string>(); | ||
* hashMap.set(1, 'A'); | ||
* hashMap.set(2, 'B'); | ||
* hashMap.set(1, 'C'); // Update value for key 1 | ||
* | ||
* console.log(hashMap.size); // 2 | ||
* console.log(hashMap.get(1)); // 'C' | ||
* console.log(hashMap.get(2)); // 'B' | ||
* @example | ||
* // count occurrences of keys | ||
* const data = [1, 2, 1, 3, 2, 1]; | ||
* | ||
* const countMap = new HashMap<number, number>(); | ||
* for (const key of data) { | ||
* countMap.set(key, (countMap.get(key) || 0) + 1); | ||
* } | ||
* | ||
* console.log(countMap.get(1)); // 3 | ||
* console.log(countMap.get(2)); // 2 | ||
* console.log(countMap.get(3)); // 1 | ||
*/ | ||
@@ -18,0 +64,0 @@ export declare class HashMap<K = any, V = any, R = [K, V]> extends IterableEntryBase<K, V> { |
@@ -12,2 +12,48 @@ "use strict"; | ||
* 4. Unordered Collection: HashMap does not guarantee the order of entries, and the order may change over time. | ||
* @example | ||
* // should maintain insertion order | ||
* const linkedHashMap = new LinkedHashMap<number, string>(); | ||
* linkedHashMap.set(1, 'A'); | ||
* linkedHashMap.set(2, 'B'); | ||
* linkedHashMap.set(3, 'C'); | ||
* | ||
* const result = Array.from(linkedHashMap); | ||
* console.log(result); // [ | ||
* // [1, 'A'], | ||
* // [2, 'B'], | ||
* // [3, 'C'] | ||
* // ] | ||
* @example | ||
* // fast lookup of values by key | ||
* const hashMap = new HashMap<number, string>(); | ||
* hashMap.set(1, 'A'); | ||
* hashMap.set(2, 'B'); | ||
* hashMap.set(3, 'C'); | ||
* | ||
* console.log(hashMap.get(1)); // 'A' | ||
* console.log(hashMap.get(2)); // 'B' | ||
* console.log(hashMap.get(3)); // 'C' | ||
* console.log(hashMap.get(99)); // undefined | ||
* @example | ||
* // remove duplicates when adding multiple entries | ||
* const hashMap = new HashMap<number, string>(); | ||
* hashMap.set(1, 'A'); | ||
* hashMap.set(2, 'B'); | ||
* hashMap.set(1, 'C'); // Update value for key 1 | ||
* | ||
* console.log(hashMap.size); // 2 | ||
* console.log(hashMap.get(1)); // 'C' | ||
* console.log(hashMap.get(2)); // 'B' | ||
* @example | ||
* // count occurrences of keys | ||
* const data = [1, 2, 1, 3, 2, 1]; | ||
* | ||
* const countMap = new HashMap<number, number>(); | ||
* for (const key of data) { | ||
* countMap.set(key, (countMap.get(key) || 0) + 1); | ||
* } | ||
* | ||
* console.log(countMap.get(1)); // 3 | ||
* console.log(countMap.get(2)); // 2 | ||
* console.log(countMap.get(3)); // 1 | ||
*/ | ||
@@ -14,0 +60,0 @@ class HashMap extends base_1.IterableEntryBase { |
@@ -28,2 +28,68 @@ /** | ||
* | ||
* @example | ||
* // implementation of a basic text editor | ||
* class TextEditor { | ||
* private content: SinglyLinkedList<string>; | ||
* private cursorIndex: number; | ||
* private undoStack: Stack<{ operation: string; data?: any }>; | ||
* | ||
* constructor() { | ||
* this.content = new SinglyLinkedList<string>(); | ||
* this.cursorIndex = 0; // Cursor starts at the beginning | ||
* this.undoStack = new Stack<{ operation: string; data?: any }>(); // Stack to keep track of operations for undo | ||
* } | ||
* | ||
* insert(char: string) { | ||
* this.content.addAt(this.cursorIndex, char); | ||
* this.cursorIndex++; | ||
* this.undoStack.push({ operation: 'insert', data: { index: this.cursorIndex - 1 } }); | ||
* } | ||
* | ||
* delete() { | ||
* if (this.cursorIndex === 0) return; // Nothing to delete | ||
* const deleted = this.content.deleteAt(this.cursorIndex - 1); | ||
* this.cursorIndex--; | ||
* this.undoStack.push({ operation: 'delete', data: { index: this.cursorIndex, char: deleted } }); | ||
* } | ||
* | ||
* moveCursor(index: number) { | ||
* this.cursorIndex = Math.max(0, Math.min(index, this.content.length)); | ||
* } | ||
* | ||
* undo() { | ||
* if (this.undoStack.size === 0) return; // No operations to undo | ||
* const lastAction = this.undoStack.pop(); | ||
* | ||
* if (lastAction!.operation === 'insert') { | ||
* this.content.deleteAt(lastAction!.data.index); | ||
* this.cursorIndex = lastAction!.data.index; | ||
* } else if (lastAction!.operation === 'delete') { | ||
* this.content.addAt(lastAction!.data.index, lastAction!.data.char); | ||
* this.cursorIndex = lastAction!.data.index + 1; | ||
* } | ||
* } | ||
* | ||
* getText(): string { | ||
* return [...this.content].join(''); | ||
* } | ||
* } | ||
* | ||
* // Example Usage | ||
* const editor = new TextEditor(); | ||
* editor.insert('H'); | ||
* editor.insert('e'); | ||
* editor.insert('l'); | ||
* editor.insert('l'); | ||
* editor.insert('o'); | ||
* console.log(editor.getText()); // 'Hello' // Output: "Hello" | ||
* | ||
* editor.delete(); | ||
* console.log(editor.getText()); // 'Hell' // Output: "Hell" | ||
* | ||
* editor.undo(); | ||
* console.log(editor.getText()); // 'Hello' // Output: "Hello" | ||
* | ||
* editor.moveCursor(1); | ||
* editor.insert('a'); | ||
* console.log(editor.getText()); // 'Haello' | ||
*/ | ||
@@ -30,0 +96,0 @@ export declare class SinglyLinkedList<E = any, R = any> extends LinearLinkedBase<E, R, SinglyLinkedListNode<E>> { |
@@ -31,2 +31,68 @@ "use strict"; | ||
* | ||
* @example | ||
* // implementation of a basic text editor | ||
* class TextEditor { | ||
* private content: SinglyLinkedList<string>; | ||
* private cursorIndex: number; | ||
* private undoStack: Stack<{ operation: string; data?: any }>; | ||
* | ||
* constructor() { | ||
* this.content = new SinglyLinkedList<string>(); | ||
* this.cursorIndex = 0; // Cursor starts at the beginning | ||
* this.undoStack = new Stack<{ operation: string; data?: any }>(); // Stack to keep track of operations for undo | ||
* } | ||
* | ||
* insert(char: string) { | ||
* this.content.addAt(this.cursorIndex, char); | ||
* this.cursorIndex++; | ||
* this.undoStack.push({ operation: 'insert', data: { index: this.cursorIndex - 1 } }); | ||
* } | ||
* | ||
* delete() { | ||
* if (this.cursorIndex === 0) return; // Nothing to delete | ||
* const deleted = this.content.deleteAt(this.cursorIndex - 1); | ||
* this.cursorIndex--; | ||
* this.undoStack.push({ operation: 'delete', data: { index: this.cursorIndex, char: deleted } }); | ||
* } | ||
* | ||
* moveCursor(index: number) { | ||
* this.cursorIndex = Math.max(0, Math.min(index, this.content.length)); | ||
* } | ||
* | ||
* undo() { | ||
* if (this.undoStack.size === 0) return; // No operations to undo | ||
* const lastAction = this.undoStack.pop(); | ||
* | ||
* if (lastAction!.operation === 'insert') { | ||
* this.content.deleteAt(lastAction!.data.index); | ||
* this.cursorIndex = lastAction!.data.index; | ||
* } else if (lastAction!.operation === 'delete') { | ||
* this.content.addAt(lastAction!.data.index, lastAction!.data.char); | ||
* this.cursorIndex = lastAction!.data.index + 1; | ||
* } | ||
* } | ||
* | ||
* getText(): string { | ||
* return [...this.content].join(''); | ||
* } | ||
* } | ||
* | ||
* // Example Usage | ||
* const editor = new TextEditor(); | ||
* editor.insert('H'); | ||
* editor.insert('e'); | ||
* editor.insert('l'); | ||
* editor.insert('l'); | ||
* editor.insert('o'); | ||
* console.log(editor.getText()); // 'Hello' // Output: "Hello" | ||
* | ||
* editor.delete(); | ||
* console.log(editor.getText()); // 'Hell' // Output: "Hell" | ||
* | ||
* editor.undo(); | ||
* console.log(editor.getText()); // 'Hello' // Output: "Hello" | ||
* | ||
* editor.moveCursor(1); | ||
* editor.insert('a'); | ||
* console.log(editor.getText()); // 'Haello' | ||
*/ | ||
@@ -33,0 +99,0 @@ class SinglyLinkedList extends linear_base_1.LinearLinkedBase { |
@@ -17,2 +17,49 @@ /** | ||
* 7. Real-time Queuing: Like queuing systems in banks or supermarkets. | ||
* @example | ||
* // Sliding Window using Queue | ||
* const nums = [2, 3, 4, 1, 5]; | ||
* const k = 2; | ||
* const queue = new Queue<number>(); | ||
* | ||
* let maxSum = 0; | ||
* let currentSum = 0; | ||
* | ||
* nums.forEach((num, i) => { | ||
* queue.push(num); | ||
* currentSum += num; | ||
* | ||
* if (queue.length > k) { | ||
* currentSum -= queue.shift()!; | ||
* } | ||
* | ||
* if (queue.length === k) { | ||
* maxSum = Math.max(maxSum, currentSum); | ||
* } | ||
* }); | ||
* | ||
* console.log(maxSum); // 7 | ||
* @example | ||
* // Breadth-First Search (BFS) using Queue | ||
* const graph: { [key in number]: number[] } = { | ||
* 1: [2, 3], | ||
* 2: [4, 5], | ||
* 3: [], | ||
* 4: [], | ||
* 5: [] | ||
* }; | ||
* | ||
* const queue = new Queue<number>(); | ||
* const visited: number[] = []; | ||
* | ||
* queue.push(1); | ||
* | ||
* while (!queue.isEmpty()) { | ||
* const node = queue.shift()!; | ||
* if (!visited.includes(node)) { | ||
* visited.push(node); | ||
* graph[node].forEach(neighbor => queue.push(neighbor)); | ||
* } | ||
* } | ||
* | ||
* console.log(visited); // [1, 2, 3, 4, 5] | ||
*/ | ||
@@ -19,0 +66,0 @@ export declare class Queue<E = any, R = any> extends LinearBase<E, R> { |
@@ -14,2 +14,49 @@ "use strict"; | ||
* 7. Real-time Queuing: Like queuing systems in banks or supermarkets. | ||
* @example | ||
* // Sliding Window using Queue | ||
* const nums = [2, 3, 4, 1, 5]; | ||
* const k = 2; | ||
* const queue = new Queue<number>(); | ||
* | ||
* let maxSum = 0; | ||
* let currentSum = 0; | ||
* | ||
* nums.forEach((num, i) => { | ||
* queue.push(num); | ||
* currentSum += num; | ||
* | ||
* if (queue.length > k) { | ||
* currentSum -= queue.shift()!; | ||
* } | ||
* | ||
* if (queue.length === k) { | ||
* maxSum = Math.max(maxSum, currentSum); | ||
* } | ||
* }); | ||
* | ||
* console.log(maxSum); // 7 | ||
* @example | ||
* // Breadth-First Search (BFS) using Queue | ||
* const graph: { [key in number]: number[] } = { | ||
* 1: [2, 3], | ||
* 2: [4, 5], | ||
* 3: [], | ||
* 4: [], | ||
* 5: [] | ||
* }; | ||
* | ||
* const queue = new Queue<number>(); | ||
* const visited: number[] = []; | ||
* | ||
* queue.push(1); | ||
* | ||
* while (!queue.isEmpty()) { | ||
* const node = queue.shift()!; | ||
* if (!visited.includes(node)) { | ||
* visited.push(node); | ||
* graph[node].forEach(neighbor => queue.push(neighbor)); | ||
* } | ||
* } | ||
* | ||
* console.log(visited); // [1, 2, 3, 4, 5] | ||
*/ | ||
@@ -16,0 +63,0 @@ class Queue extends linear_base_1.LinearBase { |
@@ -17,2 +17,123 @@ /** | ||
* 6. Backtracking Algorithms: In problems where multiple branches need to be explored but only one branch can be explored at a time, stacks can be used to save the state at each branching point. | ||
* @example | ||
* // Balanced Parentheses or Brackets | ||
* type ValidCharacters = ')' | '(' | ']' | '[' | '}' | '{'; | ||
* | ||
* const stack = new Stack<string>(); | ||
* const input: ValidCharacters[] = '[({})]'.split('') as ValidCharacters[]; | ||
* const matches: { [key in ValidCharacters]?: ValidCharacters } = { ')': '(', ']': '[', '}': '{' }; | ||
* for (const char of input) { | ||
* if ('([{'.includes(char)) { | ||
* stack.push(char); | ||
* } else if (')]}'.includes(char)) { | ||
* if (stack.pop() !== matches[char]) { | ||
* fail('Parentheses are not balanced'); | ||
* } | ||
* } | ||
* } | ||
* console.log(stack.isEmpty()); // true | ||
* @example | ||
* // Expression Evaluation and Conversion | ||
* const stack = new Stack<number>(); | ||
* const expression = [5, 3, '+']; // Equivalent to 5 + 3 | ||
* expression.forEach(token => { | ||
* if (typeof token === 'number') { | ||
* stack.push(token); | ||
* } else { | ||
* const b = stack.pop()!; | ||
* const a = stack.pop()!; | ||
* stack.push(token === '+' ? a + b : 0); // Only handling '+' here | ||
* } | ||
* }); | ||
* console.log(stack.pop()); // 8 | ||
* @example | ||
* // Depth-First Search (DFS) | ||
* const stack = new Stack<number>(); | ||
* const graph: { [key in number]: number[] } = { 1: [2, 3], 2: [4], 3: [5], 4: [], 5: [] }; | ||
* const visited: number[] = []; | ||
* stack.push(1); | ||
* while (!stack.isEmpty()) { | ||
* const node = stack.pop()!; | ||
* if (!visited.includes(node)) { | ||
* visited.push(node); | ||
* graph[node].forEach(neighbor => stack.push(neighbor)); | ||
* } | ||
* } | ||
* console.log(visited); // [1, 3, 5, 2, 4] | ||
* @example | ||
* // Backtracking Algorithms | ||
* const stack = new Stack<[number, number]>(); | ||
* const maze = [ | ||
* ['S', ' ', 'X'], | ||
* ['X', ' ', 'X'], | ||
* [' ', ' ', 'E'] | ||
* ]; | ||
* const start: [number, number] = [0, 0]; | ||
* const end = [2, 2]; | ||
* const directions = [ | ||
* [0, 1], // To the right | ||
* [1, 0], // down | ||
* [0, -1], // left | ||
* [-1, 0] // up | ||
* ]; | ||
* | ||
* const visited = new Set<string>(); // Used to record visited nodes | ||
* stack.push(start); | ||
* const path: number[][] = []; | ||
* | ||
* while (!stack.isEmpty()) { | ||
* const [x, y] = stack.pop()!; | ||
* if (visited.has(`${x},${y}`)) continue; // Skip already visited nodes | ||
* visited.add(`${x},${y}`); | ||
* | ||
* path.push([x, y]); | ||
* | ||
* if (x === end[0] && y === end[1]) { | ||
* break; // Find the end point and exit | ||
* } | ||
* | ||
* for (const [dx, dy] of directions) { | ||
* const nx = x + dx; | ||
* const ny = y + dy; | ||
* if ( | ||
* maze[nx]?.[ny] === ' ' || // feasible path | ||
* maze[nx]?.[ny] === 'E' // destination | ||
* ) { | ||
* stack.push([nx, ny]); | ||
* } | ||
* } | ||
* } | ||
* | ||
* expect(path).toContainEqual(end); | ||
* @example | ||
* // Function Call Stack | ||
* const functionStack = new Stack<string>(); | ||
* functionStack.push('main'); | ||
* functionStack.push('foo'); | ||
* functionStack.push('bar'); | ||
* console.log(functionStack.pop()); // 'bar' | ||
* console.log(functionStack.pop()); // 'foo' | ||
* console.log(functionStack.pop()); // 'main' | ||
* @example | ||
* // Simplify File Paths | ||
* const stack = new Stack<string>(); | ||
* const path = '/a/./b/../../c'; | ||
* path.split('/').forEach(segment => { | ||
* if (segment === '..') stack.pop(); | ||
* else if (segment && segment !== '.') stack.push(segment); | ||
* }); | ||
* console.log(stack.elements.join('/')); // 'c' | ||
* @example | ||
* // Stock Span Problem | ||
* const stack = new Stack<number>(); | ||
* const prices = [100, 80, 60, 70, 60, 75, 85]; | ||
* const spans: number[] = []; | ||
* prices.forEach((price, i) => { | ||
* while (!stack.isEmpty() && prices[stack.peek()!] <= price) { | ||
* stack.pop(); | ||
* } | ||
* spans.push(stack.isEmpty() ? i + 1 : i - stack.peek()!); | ||
* stack.push(i); | ||
* }); | ||
* console.log(spans); // [1, 1, 1, 2, 1, 4, 6] | ||
*/ | ||
@@ -19,0 +140,0 @@ export declare class Stack<E = any, R = any> extends IterableElementBase<E, R> { |
@@ -12,2 +12,123 @@ "use strict"; | ||
* 6. Backtracking Algorithms: In problems where multiple branches need to be explored but only one branch can be explored at a time, stacks can be used to save the state at each branching point. | ||
* @example | ||
* // Balanced Parentheses or Brackets | ||
* type ValidCharacters = ')' | '(' | ']' | '[' | '}' | '{'; | ||
* | ||
* const stack = new Stack<string>(); | ||
* const input: ValidCharacters[] = '[({})]'.split('') as ValidCharacters[]; | ||
* const matches: { [key in ValidCharacters]?: ValidCharacters } = { ')': '(', ']': '[', '}': '{' }; | ||
* for (const char of input) { | ||
* if ('([{'.includes(char)) { | ||
* stack.push(char); | ||
* } else if (')]}'.includes(char)) { | ||
* if (stack.pop() !== matches[char]) { | ||
* fail('Parentheses are not balanced'); | ||
* } | ||
* } | ||
* } | ||
* console.log(stack.isEmpty()); // true | ||
* @example | ||
* // Expression Evaluation and Conversion | ||
* const stack = new Stack<number>(); | ||
* const expression = [5, 3, '+']; // Equivalent to 5 + 3 | ||
* expression.forEach(token => { | ||
* if (typeof token === 'number') { | ||
* stack.push(token); | ||
* } else { | ||
* const b = stack.pop()!; | ||
* const a = stack.pop()!; | ||
* stack.push(token === '+' ? a + b : 0); // Only handling '+' here | ||
* } | ||
* }); | ||
* console.log(stack.pop()); // 8 | ||
* @example | ||
* // Depth-First Search (DFS) | ||
* const stack = new Stack<number>(); | ||
* const graph: { [key in number]: number[] } = { 1: [2, 3], 2: [4], 3: [5], 4: [], 5: [] }; | ||
* const visited: number[] = []; | ||
* stack.push(1); | ||
* while (!stack.isEmpty()) { | ||
* const node = stack.pop()!; | ||
* if (!visited.includes(node)) { | ||
* visited.push(node); | ||
* graph[node].forEach(neighbor => stack.push(neighbor)); | ||
* } | ||
* } | ||
* console.log(visited); // [1, 3, 5, 2, 4] | ||
* @example | ||
* // Backtracking Algorithms | ||
* const stack = new Stack<[number, number]>(); | ||
* const maze = [ | ||
* ['S', ' ', 'X'], | ||
* ['X', ' ', 'X'], | ||
* [' ', ' ', 'E'] | ||
* ]; | ||
* const start: [number, number] = [0, 0]; | ||
* const end = [2, 2]; | ||
* const directions = [ | ||
* [0, 1], // To the right | ||
* [1, 0], // down | ||
* [0, -1], // left | ||
* [-1, 0] // up | ||
* ]; | ||
* | ||
* const visited = new Set<string>(); // Used to record visited nodes | ||
* stack.push(start); | ||
* const path: number[][] = []; | ||
* | ||
* while (!stack.isEmpty()) { | ||
* const [x, y] = stack.pop()!; | ||
* if (visited.has(`${x},${y}`)) continue; // Skip already visited nodes | ||
* visited.add(`${x},${y}`); | ||
* | ||
* path.push([x, y]); | ||
* | ||
* if (x === end[0] && y === end[1]) { | ||
* break; // Find the end point and exit | ||
* } | ||
* | ||
* for (const [dx, dy] of directions) { | ||
* const nx = x + dx; | ||
* const ny = y + dy; | ||
* if ( | ||
* maze[nx]?.[ny] === ' ' || // feasible path | ||
* maze[nx]?.[ny] === 'E' // destination | ||
* ) { | ||
* stack.push([nx, ny]); | ||
* } | ||
* } | ||
* } | ||
* | ||
* expect(path).toContainEqual(end); | ||
* @example | ||
* // Function Call Stack | ||
* const functionStack = new Stack<string>(); | ||
* functionStack.push('main'); | ||
* functionStack.push('foo'); | ||
* functionStack.push('bar'); | ||
* console.log(functionStack.pop()); // 'bar' | ||
* console.log(functionStack.pop()); // 'foo' | ||
* console.log(functionStack.pop()); // 'main' | ||
* @example | ||
* // Simplify File Paths | ||
* const stack = new Stack<string>(); | ||
* const path = '/a/./b/../../c'; | ||
* path.split('/').forEach(segment => { | ||
* if (segment === '..') stack.pop(); | ||
* else if (segment && segment !== '.') stack.push(segment); | ||
* }); | ||
* console.log(stack.elements.join('/')); // 'c' | ||
* @example | ||
* // Stock Span Problem | ||
* const stack = new Stack<number>(); | ||
* const prices = [100, 80, 60, 70, 60, 75, 85]; | ||
* const spans: number[] = []; | ||
* prices.forEach((price, i) => { | ||
* while (!stack.isEmpty() && prices[stack.peek()!] <= price) { | ||
* stack.pop(); | ||
* } | ||
* spans.push(stack.isEmpty() ? i + 1 : i - stack.peek()!); | ||
* stack.push(i); | ||
* }); | ||
* console.log(spans); // [1, 1, 1, 2, 1, 4, 6] | ||
*/ | ||
@@ -14,0 +135,0 @@ class Stack extends base_1.IterableElementBase { |
{ | ||
"name": "queue-typed", | ||
"version": "2.0.0", | ||
"version": "2.0.1", | ||
"description": "Queue, ArrayQueue. Javascript & Typescript Data Structure.", | ||
@@ -118,4 +118,4 @@ "main": "dist/index.js", | ||
"dependencies": { | ||
"data-structure-typed": "^2.0.0" | ||
"data-structure-typed": "^2.0.1" | ||
} | ||
} |
@@ -97,3 +97,53 @@ ![NPM](https://img.shields.io/npm/l/queue-typed) | ||
### Sliding Window using Queue | ||
```typescript | ||
const nums = [2, 3, 4, 1, 5]; | ||
const k = 2; | ||
const queue = new Queue<number>(); | ||
let maxSum = 0; | ||
let currentSum = 0; | ||
nums.forEach((num, i) => { | ||
queue.push(num); | ||
currentSum += num; | ||
if (queue.length > k) { | ||
currentSum -= queue.shift()!; | ||
} | ||
if (queue.length === k) { | ||
maxSum = Math.max(maxSum, currentSum); | ||
} | ||
}); | ||
console.log(maxSum); // 7 | ||
``` | ||
### Breadth-First Search (BFS) using Queue | ||
```typescript | ||
const graph: { [key in number]: number[] } = { | ||
1: [2, 3], | ||
2: [4, 5], | ||
3: [], | ||
4: [], | ||
5: [] | ||
}; | ||
const queue = new Queue<number>(); | ||
const visited: number[] = []; | ||
queue.push(1); | ||
while (!queue.isEmpty()) { | ||
const node = queue.shift()!; | ||
if (!visited.includes(node)) { | ||
visited.push(node); | ||
graph[node].forEach(neighbor => queue.push(neighbor)); | ||
} | ||
} | ||
console.log(visited); // [1, 2, 3, 4, 5] | ||
``` | ||
[//]: # (No deletion!!! End of Example Replace Section) | ||
@@ -100,0 +150,0 @@ |
@@ -342,3 +342,3 @@ /** | ||
const allPaths = this.getAllPathsBetween(v1, v2); | ||
let min = Infinity; | ||
let min = Number.MAX_SAFE_INTEGER; | ||
for (const path of allPaths) { | ||
@@ -408,3 +408,3 @@ min = Math.min(this.getPathSumWeight(path), min); | ||
const allPaths = this.getAllPathsBetween(v1, v2, 10000); | ||
let min = Infinity; | ||
let min = Number.MAX_SAFE_INTEGER; | ||
let minIndex = -1; | ||
@@ -480,3 +480,3 @@ let index = 0; | ||
): DijkstraResult<VO> { | ||
let minDist = Infinity; | ||
let minDist = Number.MAX_SAFE_INTEGER; | ||
let minDest: VO | undefined = undefined; | ||
@@ -500,3 +500,3 @@ let minPath: VO[] = []; | ||
const vertexOrKey = vertex[1]; | ||
if (vertexOrKey instanceof AbstractVertex) distMap.set(vertexOrKey, Infinity); | ||
if (vertexOrKey instanceof AbstractVertex) distMap.set(vertexOrKey, Number.MAX_SAFE_INTEGER); | ||
} | ||
@@ -507,3 +507,3 @@ distMap.set(srcVertex, 0); | ||
const getMinOfNoSeen = () => { | ||
let min = Infinity; | ||
let min = Number.MAX_SAFE_INTEGER; | ||
let minV: VO | undefined = undefined; | ||
@@ -545,3 +545,3 @@ for (const [key, value] of distMap) { | ||
if (getMinDist) { | ||
minDist = distMap.get(destVertex) || Infinity; | ||
minDist = distMap.get(destVertex) || Number.MAX_SAFE_INTEGER; | ||
} | ||
@@ -614,3 +614,3 @@ if (genPaths) { | ||
): DijkstraResult<VO> { | ||
let minDist = Infinity; | ||
let minDist = Number.MAX_SAFE_INTEGER; | ||
let minDest: VO | undefined = undefined; | ||
@@ -631,3 +631,3 @@ let minPath: VO[] = []; | ||
const vertexOrKey = vertex[1]; | ||
if (vertexOrKey instanceof AbstractVertex) distMap.set(vertexOrKey, Infinity); | ||
if (vertexOrKey instanceof AbstractVertex) distMap.set(vertexOrKey, Number.MAX_SAFE_INTEGER); | ||
} | ||
@@ -672,3 +672,3 @@ | ||
if (getMinDist) { | ||
minDist = distMap.get(destVertex) || Infinity; | ||
minDist = distMap.get(destVertex) || Number.MAX_SAFE_INTEGER; | ||
} | ||
@@ -744,3 +744,3 @@ if (genPaths) { | ||
const preMap: Map<VO, VO> = new Map(); // predecessor | ||
let min = Infinity; | ||
let min = Number.MAX_SAFE_INTEGER; | ||
let minPath: VO[] = []; | ||
@@ -758,3 +758,3 @@ // TODO | ||
this._vertexMap.forEach(vertex => { | ||
distMap.set(vertex, Infinity); | ||
distMap.set(vertex, Number.MAX_SAFE_INTEGER); | ||
}); | ||
@@ -773,3 +773,3 @@ | ||
if (sWeight !== undefined && dWeight !== undefined) { | ||
if (distMap.get(s) !== Infinity && sWeight + weight < dWeight) { | ||
if (distMap.get(s) !== Number.MAX_SAFE_INTEGER && sWeight + weight < dWeight) { | ||
distMap.set(d, sWeight + weight); | ||
@@ -819,3 +819,3 @@ if (genPath) preMap.set(d, s); | ||
if (sWeight) { | ||
if (sWeight !== Infinity && sWeight + weight < sWeight) hasNegativeCycle = true; | ||
if (sWeight !== Number.MAX_SAFE_INTEGER && sWeight + weight < sWeight) hasNegativeCycle = true; | ||
} | ||
@@ -876,3 +876,3 @@ } | ||
for (let j = 0; j < n; j++) { | ||
costs[i][j] = this.getEdge(idAndVertices[i][1], idAndVertices[j][1])?.weight || Infinity; | ||
costs[i][j] = this.getEdge(idAndVertices[i][1], idAndVertices[j][1])?.weight || Number.MAX_SAFE_INTEGER; | ||
} | ||
@@ -879,0 +879,0 @@ } |
@@ -24,2 +24,48 @@ /** | ||
* 4. Unordered Collection: HashMap does not guarantee the order of entries, and the order may change over time. | ||
* @example | ||
* // should maintain insertion order | ||
* const linkedHashMap = new LinkedHashMap<number, string>(); | ||
* linkedHashMap.set(1, 'A'); | ||
* linkedHashMap.set(2, 'B'); | ||
* linkedHashMap.set(3, 'C'); | ||
* | ||
* const result = Array.from(linkedHashMap); | ||
* console.log(result); // [ | ||
* // [1, 'A'], | ||
* // [2, 'B'], | ||
* // [3, 'C'] | ||
* // ] | ||
* @example | ||
* // fast lookup of values by key | ||
* const hashMap = new HashMap<number, string>(); | ||
* hashMap.set(1, 'A'); | ||
* hashMap.set(2, 'B'); | ||
* hashMap.set(3, 'C'); | ||
* | ||
* console.log(hashMap.get(1)); // 'A' | ||
* console.log(hashMap.get(2)); // 'B' | ||
* console.log(hashMap.get(3)); // 'C' | ||
* console.log(hashMap.get(99)); // undefined | ||
* @example | ||
* // remove duplicates when adding multiple entries | ||
* const hashMap = new HashMap<number, string>(); | ||
* hashMap.set(1, 'A'); | ||
* hashMap.set(2, 'B'); | ||
* hashMap.set(1, 'C'); // Update value for key 1 | ||
* | ||
* console.log(hashMap.size); // 2 | ||
* console.log(hashMap.get(1)); // 'C' | ||
* console.log(hashMap.get(2)); // 'B' | ||
* @example | ||
* // count occurrences of keys | ||
* const data = [1, 2, 1, 3, 2, 1]; | ||
* | ||
* const countMap = new HashMap<number, number>(); | ||
* for (const key of data) { | ||
* countMap.set(key, (countMap.get(key) || 0) + 1); | ||
* } | ||
* | ||
* console.log(countMap.get(1)); // 3 | ||
* console.log(countMap.get(2)); // 2 | ||
* console.log(countMap.get(3)); // 1 | ||
*/ | ||
@@ -26,0 +72,0 @@ export class HashMap<K = any, V = any, R = [K, V]> extends IterableEntryBase<K, V> { |
@@ -41,2 +41,68 @@ /** | ||
* | ||
* @example | ||
* // implementation of a basic text editor | ||
* class TextEditor { | ||
* private content: SinglyLinkedList<string>; | ||
* private cursorIndex: number; | ||
* private undoStack: Stack<{ operation: string; data?: any }>; | ||
* | ||
* constructor() { | ||
* this.content = new SinglyLinkedList<string>(); | ||
* this.cursorIndex = 0; // Cursor starts at the beginning | ||
* this.undoStack = new Stack<{ operation: string; data?: any }>(); // Stack to keep track of operations for undo | ||
* } | ||
* | ||
* insert(char: string) { | ||
* this.content.addAt(this.cursorIndex, char); | ||
* this.cursorIndex++; | ||
* this.undoStack.push({ operation: 'insert', data: { index: this.cursorIndex - 1 } }); | ||
* } | ||
* | ||
* delete() { | ||
* if (this.cursorIndex === 0) return; // Nothing to delete | ||
* const deleted = this.content.deleteAt(this.cursorIndex - 1); | ||
* this.cursorIndex--; | ||
* this.undoStack.push({ operation: 'delete', data: { index: this.cursorIndex, char: deleted } }); | ||
* } | ||
* | ||
* moveCursor(index: number) { | ||
* this.cursorIndex = Math.max(0, Math.min(index, this.content.length)); | ||
* } | ||
* | ||
* undo() { | ||
* if (this.undoStack.size === 0) return; // No operations to undo | ||
* const lastAction = this.undoStack.pop(); | ||
* | ||
* if (lastAction!.operation === 'insert') { | ||
* this.content.deleteAt(lastAction!.data.index); | ||
* this.cursorIndex = lastAction!.data.index; | ||
* } else if (lastAction!.operation === 'delete') { | ||
* this.content.addAt(lastAction!.data.index, lastAction!.data.char); | ||
* this.cursorIndex = lastAction!.data.index + 1; | ||
* } | ||
* } | ||
* | ||
* getText(): string { | ||
* return [...this.content].join(''); | ||
* } | ||
* } | ||
* | ||
* // Example Usage | ||
* const editor = new TextEditor(); | ||
* editor.insert('H'); | ||
* editor.insert('e'); | ||
* editor.insert('l'); | ||
* editor.insert('l'); | ||
* editor.insert('o'); | ||
* console.log(editor.getText()); // 'Hello' // Output: "Hello" | ||
* | ||
* editor.delete(); | ||
* console.log(editor.getText()); // 'Hell' // Output: "Hell" | ||
* | ||
* editor.undo(); | ||
* console.log(editor.getText()); // 'Hello' // Output: "Hello" | ||
* | ||
* editor.moveCursor(1); | ||
* editor.insert('a'); | ||
* console.log(editor.getText()); // 'Haello' | ||
*/ | ||
@@ -43,0 +109,0 @@ export class SinglyLinkedList<E = any, R = any> extends LinearLinkedBase<E, R, SinglyLinkedListNode<E>> { |
@@ -18,2 +18,49 @@ /** | ||
* 7. Real-time Queuing: Like queuing systems in banks or supermarkets. | ||
* @example | ||
* // Sliding Window using Queue | ||
* const nums = [2, 3, 4, 1, 5]; | ||
* const k = 2; | ||
* const queue = new Queue<number>(); | ||
* | ||
* let maxSum = 0; | ||
* let currentSum = 0; | ||
* | ||
* nums.forEach((num, i) => { | ||
* queue.push(num); | ||
* currentSum += num; | ||
* | ||
* if (queue.length > k) { | ||
* currentSum -= queue.shift()!; | ||
* } | ||
* | ||
* if (queue.length === k) { | ||
* maxSum = Math.max(maxSum, currentSum); | ||
* } | ||
* }); | ||
* | ||
* console.log(maxSum); // 7 | ||
* @example | ||
* // Breadth-First Search (BFS) using Queue | ||
* const graph: { [key in number]: number[] } = { | ||
* 1: [2, 3], | ||
* 2: [4, 5], | ||
* 3: [], | ||
* 4: [], | ||
* 5: [] | ||
* }; | ||
* | ||
* const queue = new Queue<number>(); | ||
* const visited: number[] = []; | ||
* | ||
* queue.push(1); | ||
* | ||
* while (!queue.isEmpty()) { | ||
* const node = queue.shift()!; | ||
* if (!visited.includes(node)) { | ||
* visited.push(node); | ||
* graph[node].forEach(neighbor => queue.push(neighbor)); | ||
* } | ||
* } | ||
* | ||
* console.log(visited); // [1, 2, 3, 4, 5] | ||
*/ | ||
@@ -20,0 +67,0 @@ export class Queue<E = any, R = any> extends LinearBase<E, R> { |
@@ -18,2 +18,123 @@ /** | ||
* 6. Backtracking Algorithms: In problems where multiple branches need to be explored but only one branch can be explored at a time, stacks can be used to save the state at each branching point. | ||
* @example | ||
* // Balanced Parentheses or Brackets | ||
* type ValidCharacters = ')' | '(' | ']' | '[' | '}' | '{'; | ||
* | ||
* const stack = new Stack<string>(); | ||
* const input: ValidCharacters[] = '[({})]'.split('') as ValidCharacters[]; | ||
* const matches: { [key in ValidCharacters]?: ValidCharacters } = { ')': '(', ']': '[', '}': '{' }; | ||
* for (const char of input) { | ||
* if ('([{'.includes(char)) { | ||
* stack.push(char); | ||
* } else if (')]}'.includes(char)) { | ||
* if (stack.pop() !== matches[char]) { | ||
* fail('Parentheses are not balanced'); | ||
* } | ||
* } | ||
* } | ||
* console.log(stack.isEmpty()); // true | ||
* @example | ||
* // Expression Evaluation and Conversion | ||
* const stack = new Stack<number>(); | ||
* const expression = [5, 3, '+']; // Equivalent to 5 + 3 | ||
* expression.forEach(token => { | ||
* if (typeof token === 'number') { | ||
* stack.push(token); | ||
* } else { | ||
* const b = stack.pop()!; | ||
* const a = stack.pop()!; | ||
* stack.push(token === '+' ? a + b : 0); // Only handling '+' here | ||
* } | ||
* }); | ||
* console.log(stack.pop()); // 8 | ||
* @example | ||
* // Depth-First Search (DFS) | ||
* const stack = new Stack<number>(); | ||
* const graph: { [key in number]: number[] } = { 1: [2, 3], 2: [4], 3: [5], 4: [], 5: [] }; | ||
* const visited: number[] = []; | ||
* stack.push(1); | ||
* while (!stack.isEmpty()) { | ||
* const node = stack.pop()!; | ||
* if (!visited.includes(node)) { | ||
* visited.push(node); | ||
* graph[node].forEach(neighbor => stack.push(neighbor)); | ||
* } | ||
* } | ||
* console.log(visited); // [1, 3, 5, 2, 4] | ||
* @example | ||
* // Backtracking Algorithms | ||
* const stack = new Stack<[number, number]>(); | ||
* const maze = [ | ||
* ['S', ' ', 'X'], | ||
* ['X', ' ', 'X'], | ||
* [' ', ' ', 'E'] | ||
* ]; | ||
* const start: [number, number] = [0, 0]; | ||
* const end = [2, 2]; | ||
* const directions = [ | ||
* [0, 1], // To the right | ||
* [1, 0], // down | ||
* [0, -1], // left | ||
* [-1, 0] // up | ||
* ]; | ||
* | ||
* const visited = new Set<string>(); // Used to record visited nodes | ||
* stack.push(start); | ||
* const path: number[][] = []; | ||
* | ||
* while (!stack.isEmpty()) { | ||
* const [x, y] = stack.pop()!; | ||
* if (visited.has(`${x},${y}`)) continue; // Skip already visited nodes | ||
* visited.add(`${x},${y}`); | ||
* | ||
* path.push([x, y]); | ||
* | ||
* if (x === end[0] && y === end[1]) { | ||
* break; // Find the end point and exit | ||
* } | ||
* | ||
* for (const [dx, dy] of directions) { | ||
* const nx = x + dx; | ||
* const ny = y + dy; | ||
* if ( | ||
* maze[nx]?.[ny] === ' ' || // feasible path | ||
* maze[nx]?.[ny] === 'E' // destination | ||
* ) { | ||
* stack.push([nx, ny]); | ||
* } | ||
* } | ||
* } | ||
* | ||
* expect(path).toContainEqual(end); | ||
* @example | ||
* // Function Call Stack | ||
* const functionStack = new Stack<string>(); | ||
* functionStack.push('main'); | ||
* functionStack.push('foo'); | ||
* functionStack.push('bar'); | ||
* console.log(functionStack.pop()); // 'bar' | ||
* console.log(functionStack.pop()); // 'foo' | ||
* console.log(functionStack.pop()); // 'main' | ||
* @example | ||
* // Simplify File Paths | ||
* const stack = new Stack<string>(); | ||
* const path = '/a/./b/../../c'; | ||
* path.split('/').forEach(segment => { | ||
* if (segment === '..') stack.pop(); | ||
* else if (segment && segment !== '.') stack.push(segment); | ||
* }); | ||
* console.log(stack.elements.join('/')); // 'c' | ||
* @example | ||
* // Stock Span Problem | ||
* const stack = new Stack<number>(); | ||
* const prices = [100, 80, 60, 70, 60, 75, 85]; | ||
* const spans: number[] = []; | ||
* prices.forEach((price, i) => { | ||
* while (!stack.isEmpty() && prices[stack.peek()!] <= price) { | ||
* stack.pop(); | ||
* } | ||
* spans.push(stack.isEmpty() ? i + 1 : i - stack.peek()!); | ||
* stack.push(i); | ||
* }); | ||
* console.log(spans); // [1, 1, 1, 2, 1, 4, 6] | ||
*/ | ||
@@ -20,0 +141,0 @@ export class Stack<E = any, R = any> extends IterableElementBase<E, R> { |
2472392
48799
281
Updateddata-structure-typed@^2.0.1