diff --git a/README.md b/README.md index 37292d0..514c6bf 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,19 @@ +# What -Javascript Data Structure, TypeScript Data Structure Library +## Brief +Javascript & TypeScript Data Structure Library. + +Meticulously crafted to empower developers with a versatile set of essential data structures. Our library includes a +wide range of data structures + +## Data Structures + +Binary Tree, Binary Search Tree (BST), AVL Tree, Tree Multiset, Segment Tree, Binary Indexed Tree, Graph, Directed +Graph, Undirected Graph, Linked List, Singly Linked List, Doubly Linked List, Queue, Object Deque, Array Deque, Stack, +Hash, Coordinate Set, Coordinate Map, Heap, Priority Queue, Max Priority Queue, Min Priority Queue, Trie + + +# How ## install @@ -15,19 +29,374 @@ yarn add data-structure-typed npm install data-structure-typed ``` +### Binary Search Tree (BST) snippet + +```typescript + import {BST, BSTNode} from 'data-structure-typed'; + + const tree = new BST(); + expect(tree).toBeInstanceOf(BST); + + const ids = [11, 3, 15, 1, 8, 13, 16, 2, 6, 9, 12, 14, 4, 7, 10, 5]; + tree.addMany(ids); + expect(tree.root).toBeInstanceOf(BSTNode); + if (tree.root) expect(tree.root.id).toBe(11); + expect(tree.count).toBe(16); + expect(tree.has(6)).toBe(true); + + const node6 = tree.get(6); + expect(node6 && tree.getHeight(node6)).toBe(2); + expect(node6 && tree.getDepth(node6)).toBe(3); + + const nodeId10 = tree.get(10, 'id'); + expect(nodeId10?.id).toBe(10); + + const nodeVal9 = tree.get(9, 'val'); + expect(nodeVal9?.id).toBe(9); + + const nodesByCount1 = tree.getNodes(1, 'count'); + expect(nodesByCount1.length).toBe(16); + + const leftMost = tree.getLeftMost(); + expect(leftMost?.id).toBe(1); + + const node15 = tree.get(15); + const minNodeBySpecificNode = node15 && tree.getLeftMost(node15); + expect(minNodeBySpecificNode?.id).toBe(12); + + const subTreeSum = node15 && tree.subTreeSum(node15); + expect(subTreeSum).toBe(70); + + const lesserSum = tree.lesserSum(10); + expect(lesserSum).toBe(45); + + expect(node15).toBeInstanceOf(BSTNode); + if (node15 instanceof BSTNode) { + const subTreeAdd = tree.subTreeAdd(node15, 1, 'count'); + expect(subTreeAdd).toBeDefined(); + } + + const node11 = tree.get(11); + expect(node11).toBeInstanceOf(BSTNode); + if (node11 instanceof BSTNode) { + const allGreaterNodesAdded = tree.allGreaterNodesAdd(node11, 2, 'count'); + expect(allGreaterNodesAdded).toBeDefined(); + } + + const dfsInorderNodes = tree.DFS('in', 'node'); + expect(dfsInorderNodes[0].id).toBe(1); + expect(dfsInorderNodes[dfsInorderNodes.length - 1].id).toBe(16); + + tree.balance(); + expect(tree.isBalanced()).toBe(true); + + const bfsNodesAfterBalanced = tree.BFS('node'); + expect(bfsNodesAfterBalanced[0].id).toBe(8); + expect(bfsNodesAfterBalanced[bfsNodesAfterBalanced.length - 1].id).toBe(16); + + const removed11 = tree.remove(11, true); + expect(removed11).toBeInstanceOf(Array); + expect(removed11[0]).toBeDefined(); + expect(removed11[0].deleted).toBeDefined(); + + if (removed11[0].deleted) expect(removed11[0].deleted.id).toBe(11); + + expect(tree.isAVLBalanced()).toBe(true); + + expect(node15 && tree.getHeight(node15)).toBe(2); + + const removed1 = tree.remove(1, true); + expect(removed1).toBeInstanceOf(Array); + expect(removed1[0]).toBeDefined(); + expect(removed1[0].deleted).toBeDefined(); + if (removed1[0].deleted) expect(removed1[0].deleted.id).toBe(1); + + expect(tree.isAVLBalanced()).toBe(true); + + expect(tree.getHeight()).toBe(4); + + // The code for removing these nodes (4, 10, 15, 5, 13, 3, 8, 6, 7, 9, 14) in sequence has been omitted. + + expect(tree.isAVLBalanced()).toBe(false); + + const bfsIDs = tree.BFS(); + expect(bfsIDs[0]).toBe(2); + expect(bfsIDs[1]).toBe(12); + expect(bfsIDs[2]).toBe(16); + + const bfsNodes = tree.BFS('node'); + expect(bfsNodes[0].id).toBe(2); + expect(bfsNodes[1].id).toBe(12); + expect(bfsNodes[2].id).toBe(16); +``` + ## Live Examples [//]: # ([Live Examples](https://data-structure-typed-examples.vercel.app)) Live Examples -## Data Structures +### Directed Graph simple snippet -Meticulously crafted to empower developers with a versatile set of essential data structures. Our library includes a -wide range of data structures: -Binary Tree, Binary Search Tree (BST), AVL Tree, Tree Multiset, Segment Tree, Binary Indexed Tree, Graph, Directed -Graph, Undirected Graph, Linked List, Singly Linked List, Doubly Linked List, Queue, Object Deque, Array Deque, Stack, -Hash, Coordinate Set, Coordinate Map, Heap, Priority Queue, Max Priority Queue, Min Priority Queue, Trie +```typescript +import {DirectedGraph, DirectedVertex, DirectedEdge, VertexId} from 'data-structure-typed'; + +let graph: DirectedGraph; + + beforeEach(() => { + graph = new DirectedGraph(); + }); + + + it('should add vertices', () => { + const vertex1 = new DirectedVertex('A'); + const vertex2 = new DirectedVertex('B'); + + graph.addVertex(vertex1); + graph.addVertex(vertex2); + + expect(graph.hasVertex(vertex1)).toBe(true); + expect(graph.hasVertex(vertex2)).toBe(true); + }); + + it('should add edges', () => { + const vertex1 = new DirectedVertex('A'); + const vertex2 = new DirectedVertex('B'); + const edge = new DirectedEdge('A', 'B'); + + graph.addVertex(vertex1); + graph.addVertex(vertex2); + graph.addEdge(edge); + + expect(graph.hasEdge('A', 'B')).toBe(true); + expect(graph.hasEdge('B', 'A')).toBe(false); + }); + + it('should remove edges', () => { + const vertex1 = new DirectedVertex('A'); + const vertex2 = new DirectedVertex('B'); + const edge = new DirectedEdge('A', 'B'); + + graph.addVertex(vertex1); + graph.addVertex(vertex2); + graph.addEdge(edge); + + expect(graph.removeEdge(edge)).toBe(edge); + expect(graph.hasEdge('A', 'B')).toBe(false); + }); + + it('should perform topological sort', () => { + const vertexA = new DirectedVertex('A'); + const vertexB = new DirectedVertex('B'); + const vertexC = new DirectedVertex('C'); + const edgeAB = new DirectedEdge('A', 'B'); + const edgeBC = new DirectedEdge('B', 'C'); + + graph.addVertex(vertexA); + graph.addVertex(vertexB); + graph.addVertex(vertexC); + graph.addEdge(edgeAB); + graph.addEdge(edgeBC); + + const topologicalOrder = graph.topologicalSort(); + if (topologicalOrder) expect(topologicalOrder.map(v => v.id)).toEqual(['A', 'B', 'C']); + }); +``` + +### Directed Graph complex snippet + +```typescript +import {DirectedGraph, DirectedVertex, DirectedEdge, VertexId} from 'data-structure-typed'; + +class MyVertex extends DirectedVertex { + private _data: string; + get data(): string { + return this._data; + } + set data(value: string) { + this._data = value; + } + + constructor(id: VertexId, data: string) { + super(id); + this._data = data; + } +} + +class MyEdge extends DirectedEdge { + private _data: string; + get data(): string { + return this._data; + } + set data(value: string) { + this._data = value; + } + + constructor(v1: VertexId, v2: VertexId, weight: number, data: string) { + super(v1, v2, weight); + this._data = data; + } +} + +describe('DirectedGraph Test3', () => { + const myGraph = new DirectedGraph(); + + it('should test graph operations', () => { + const vertex1 = new MyVertex(1, 'data1'); + const vertex2 = new MyVertex(2, 'data2'); + const vertex3 = new MyVertex(3, 'data3'); + const vertex4 = new MyVertex(4, 'data4'); + const vertex5 = new MyVertex(5, 'data5'); + const vertex6 = new MyVertex(6, 'data6'); + const vertex7 = new MyVertex(7, 'data7'); + const vertex8 = new MyVertex(8, 'data8'); + const vertex9 = new MyVertex(9, 'data9'); + myGraph.addVertex(vertex1); + myGraph.addVertex(vertex2); + myGraph.addVertex(vertex3); + myGraph.addVertex(vertex4); + myGraph.addVertex(vertex5); + myGraph.addVertex(vertex6); + myGraph.addVertex(vertex7); + myGraph.addVertex(vertex8); + myGraph.addVertex(vertex9); + + myGraph.addEdge(new MyEdge(1, 2, 10, 'edge-data1-2')); + myGraph.addEdge(new MyEdge(2, 1, 20, 'edge-data2-1')); + + expect(myGraph.getEdge(1, 2)).toBeTruthy(); + expect(myGraph.getEdge(2, 1)).toBeTruthy(); + expect(myGraph.getEdge(1, '100')).toBeFalsy(); + + myGraph.removeEdgeBetween(1, 2); + expect(myGraph.getEdge(1, 2)).toBeFalsy(); + + myGraph.addEdge(new MyEdge(3, 1, 3, 'edge-data-3-1')); + myGraph.addEdge(new MyEdge(1, 9, 19, 'edge-data1-9')); + myGraph.addEdge(new MyEdge(9, 7, 97, 'edge-data9-7')); + myGraph.addEdge(new MyEdge(7, 9, 79, 'edge-data7-9')); + myGraph.addEdge(new MyEdge(1, 4, 14, 'edge-data1-4')); + myGraph.addEdge(new MyEdge(4, 7, 47, 'edge-data4-7')); + myGraph.addEdge(new MyEdge(1, 2, 12, 'edge-data1-2')); + myGraph.addEdge(new MyEdge(2, 3, 23, 'edge-data2-3')); + myGraph.addEdge(new MyEdge(3, 5, 35, 'edge-data3-5')); + myGraph.addEdge(new MyEdge(5, 7, 57, 'edge-data5-7')); + myGraph.addEdge(new MyEdge(7, 3, 73, 'edge-data7-3')); + + const topologicalSorted = myGraph.topologicalSort(); + expect(topologicalSorted).toBeNull(); + + const minPath1to7 = myGraph.getMinPathBetween(1, 7); + expect(minPath1to7).toBeInstanceOf(Array); + if (minPath1to7 && minPath1to7.length > 0) { + expect(minPath1to7).toHaveLength(3); + expect(minPath1to7[0]).toBeInstanceOf(MyVertex); + expect(minPath1to7[0].id).toBe(1); + expect(minPath1to7[1].id).toBe(9); + expect(minPath1to7[2].id).toBe(7); + } + + const fordResult1 = myGraph.bellmanFord(1); + expect(fordResult1).toBeTruthy(); + expect(fordResult1.hasNegativeCycle).toBeUndefined(); + const {distMap, preMap, paths, min, minPath} = fordResult1; + expect(distMap).toBeInstanceOf(Map); + expect(distMap.size).toBe(9); + expect(distMap.get(vertex1)).toBe(0); + expect(distMap.get(vertex2)).toBe(12); + expect(distMap.get(vertex3)).toBe(35); + expect(distMap.get(vertex4)).toBe(14); + expect(distMap.get(vertex5)).toBe(70); + expect(distMap.get(vertex6)).toBe(Infinity); + expect(distMap.get(vertex7)).toBe(61); + expect(distMap.get(vertex8)).toBe(Infinity); + expect(distMap.get(vertex9)).toBe(19); + + expect(preMap).toBeInstanceOf(Map); + expect(preMap.size).toBe(0); + + expect(paths).toBeInstanceOf(Array); + expect(paths.length).toBe(0); + expect(min).toBe(Infinity); + expect(minPath).toBeInstanceOf(Array); + + const floydResult = myGraph.floyd(); + expect(floydResult).toBeTruthy(); + if (floydResult) { + const {costs, predecessor} = floydResult; + expect(costs).toBeInstanceOf(Array); + expect(costs.length).toBe(9); + expect(costs[0]).toEqual([32, 12, 35, 14, 70, Infinity, 61, Infinity, 19]); + expect(costs[1]).toEqual([20, 32, 23, 34, 58, Infinity, 81, Infinity, 39]); + expect(costs[2]).toEqual([3, 15, 38, 17, 35, Infinity, 64, Infinity, 22]); + expect(costs[3]).toEqual([123, 135, 120, 137, 155, Infinity, 47, Infinity, 126]); + expect(costs[4]).toEqual([133, 145, 130, 147, 165, Infinity, 57, Infinity, 136]); + expect(costs[5]).toEqual([Infinity, Infinity, Infinity, Infinity, Infinity, Infinity, Infinity, Infinity, Infinity]); + expect(costs[6]).toEqual([76, 88, 73, 90, 108, Infinity, 137, Infinity, 79]); + expect(costs[7]).toEqual([Infinity, Infinity, Infinity, Infinity, Infinity, Infinity, Infinity, Infinity, Infinity]); + expect(costs[8]).toEqual([173, 185, 170, 187, 205, Infinity, 97, Infinity, 176]); + + expect(predecessor).toBeInstanceOf(Array); + expect(predecessor.length).toBe(9); + expect(predecessor[0]).toEqual([vertex2, null, vertex2, null, vertex3, null, vertex4, null, null]); + expect(predecessor[1]).toEqual([null, vertex1, null, vertex1, vertex3, null, vertex4, null, vertex1]); + expect(predecessor[5]).toEqual([null, null, null, null, null, null, null, null, null]); + expect(predecessor[7]).toEqual([null, null, null, null, null, null, null, null, null]); + expect(predecessor[8]).toEqual([vertex7, vertex7, vertex7, vertex7, vertex7, null, null, null, vertex7]); + } + + const dijkstraRes12tt = myGraph.dijkstra(1, 2, true, true); + expect(dijkstraRes12tt).toBeTruthy(); + if (dijkstraRes12tt) { + const {distMap, minDist, minPath, paths, preMap, seen} = dijkstraRes12tt; + expect(distMap).toBeInstanceOf(Map); + expect(distMap.size).toBe(9); + expect(distMap.get(vertex1)).toBe(0); + expect(distMap.get(vertex2)).toBe(12); + expect(distMap.get(vertex3)).toBe(Infinity); + expect(distMap.get(vertex4)).toBe(14); + expect(distMap.get(vertex5)).toBe(Infinity); + expect(distMap.get(vertex6)).toBe(Infinity); + expect(distMap.get(vertex7)).toBe(Infinity); + expect(distMap.get(vertex8)).toBe(Infinity); + expect(distMap.get(vertex9)).toBe(19); + + expect(minDist).toBe(12); + expect(minPath).toBeInstanceOf(Array); + expect(minPath.length).toBe(2); + expect(minPath[0]).toBe(vertex1); + expect(minPath[1]).toBe(vertex2); + + expect(paths).toBeInstanceOf(Array); + expect(paths.length).toBe(9); + expect(paths[0]).toBeInstanceOf(Array); + expect(paths[0][0]).toBe(vertex1); + + expect(paths[1]).toBeInstanceOf(Array); + expect(paths[1][0]).toBe(vertex1); + expect(paths[1][1]).toBe(vertex2); + + expect(paths[2]).toBeInstanceOf(Array); + expect(paths[2][0]).toBe(vertex3); + expect(paths[3]).toBeInstanceOf(Array); + expect(paths[3][0]).toBe(vertex1); + expect(paths[3][1]).toBe(vertex4); + expect(paths[4]).toBeInstanceOf(Array); + expect(paths[4][0]).toBe(vertex5); + + expect(paths[5]).toBeInstanceOf(Array); + expect(paths[5][0]).toBe(vertex6); + expect(paths[6]).toBeInstanceOf(Array); + expect(paths[6][0]).toBe(vertex7); + expect(paths[7]).toBeInstanceOf(Array); + expect(paths[7][0]).toBe(vertex8); + expect(paths[8]).toBeInstanceOf(Array); + expect(paths[8][0]).toBe(vertex1); + expect(paths[8][1]).toBe(vertex9); + } + }); +}); +``` ## API docs @@ -99,6 +468,7 @@ Hash, Coordinate Set, Coordinate Map, Heap, Priority Queue, Max Priority Queue, Examples Repository +# Why ## Complexities @@ -363,6 +733,7 @@ Hash, Coordinate Set, Coordinate Map, Heap, Priority Queue, Max Priority Queue, +![overview diagram](src/assets/overview-diagram-of-data-structures.png) ![complexities](src/assets/complexities-diff.jpg) diff --git a/package-lock.json b/package-lock.json index c3ed1c3..3a0dbdb 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,19 +1,15 @@ { "name": "data-structure-typed", - "version": "1.12.21", + "version": "1.15.2", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "data-structure-typed", - "version": "1.12.21", + "version": "1.15.2", "license": "MIT", - "dependencies": { - "lodash": "^4.17.21" - }, "devDependencies": { "@types/jest": "^29.5.3", - "@types/lodash": "^4.14.197", "@types/node": "^20.4.9", "dependency-cruiser": "^13.1.2", "jest": "^29.6.2", @@ -1466,12 +1462,6 @@ "pretty-format": "^29.0.0" } }, - "node_modules/@types/lodash": { - "version": "4.14.197", - "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.197.tgz", - "integrity": "sha512-BMVOiWs0uNxHVlHBgzTIqJYmj+PgCo4euloGF+5m4okL3rEYzM2EEv78mw8zWSMM57dM7kVIgJ2QDvwHSoCI5g==", - "dev": true - }, "node_modules/@types/node": { "version": "20.5.0", "resolved": "https://registry.npmjs.org/@types/node/-/node-20.5.0.tgz", @@ -1875,9 +1865,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001520", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001520.tgz", - "integrity": "sha512-tahF5O9EiiTzwTUqAeFjIZbn4Dnqxzz7ktrgGlMYNLH43Ul26IgTMH/zvL3DG0lZxBYnlT04axvInszUsZULdA==", + "version": "1.0.30001521", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001521.tgz", + "integrity": "sha512-fnx1grfpEOvDGH+V17eccmNjucGUnCbP6KL+l5KqBIerp26WK/+RQ7CIDE37KGJjaPyqWXXlFUyKiWmvdNNKmQ==", "dev": true, "funding": [ { @@ -2863,9 +2853,9 @@ } }, "node_modules/jackspeak": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-2.2.3.tgz", - "integrity": "sha512-pF0kfjmg8DJLxDrizHoCZGUFz4P4czQ3HyfW4BU0ffebYkzAVlBywp5zaxW/TM+r0sGbmrQdi8EQQVTJFxnGsQ==", + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-2.3.0.tgz", + "integrity": "sha512-uKmsITSsF4rUWQHzqaRUuyAir3fZfW3f202Ee34lz/gZCi970CPZwyQXLGNgWJvvZbvFyzeyGq0+4fcG/mBKZg==", "dev": true, "dependencies": { "@isaacs/cliui": "^8.0.2" @@ -4305,7 +4295,8 @@ "node_modules/lodash": { "version": "4.17.21", "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", + "dev": true }, "node_modules/lodash.memoize": { "version": "4.1.2", diff --git a/package.json b/package.json index e6b8bb9..ce8bd14 100644 --- a/package.json +++ b/package.json @@ -1,13 +1,14 @@ { "name": "data-structure-typed", - "version": "1.15.0", + "version": "1.15.2", "description": "Explore our comprehensive Javascript Data Structure / TypeScript Data Structure Library, meticulously crafted to empower developers with a versatile set of essential data structures. Our library includes a wide range of data structures, such as Binary Tree, AVL Tree, Binary Search Tree (BST), Tree Multiset, Segment Tree, Binary Indexed Tree, Graph, Directed Graph, Undirected Graph, Singly Linked List, Hash, CoordinateSet, CoordinateMap, Heap, Doubly Linked List, Priority Queue, Max Priority Queue, Min Priority Queue, Queue, ObjectDeque, ArrayDeque, Stack, and Trie. Each data structure is thoughtfully designed and implemented using TypeScript to provide efficient, reliable, and easy-to-use solutions for your programming needs. Whether you're optimizing algorithms, managing data, or enhancing performance, our TypeScript Data Structure Library is your go-to resource. Elevate your coding experience with these fundamental building blocks for software development.", "main": "dist/index.js", "scripts": { "build": "rm -rf dist && npx tsc", "test": "jest", "build:docs": "typedoc --out docs ./src", - "deps:check": "dependency-cruiser src" + "deps:check": "dependency-cruiser src", + "build:publish": "npm run test && npm run build && npm run build:docs && npm publish" }, "repository": { "type": "git", @@ -48,7 +49,6 @@ "types": "dist/index.d.ts", "devDependencies": { "@types/jest": "^29.5.3", - "@types/lodash": "^4.14.197", "@types/node": "^20.4.9", "dependency-cruiser": "^13.1.2", "jest": "^29.6.2", @@ -57,6 +57,5 @@ "typescript": "^4.9.5" }, "dependencies": { - "lodash": "^4.17.21" } } diff --git a/src/assets/overview-diagram-of-data-structures.png b/src/assets/overview-diagram-of-data-structures.png new file mode 100644 index 0000000..55a3403 Binary files /dev/null and b/src/assets/overview-diagram-of-data-structures.png differ diff --git a/src/data-structures/binary-tree/binary-tree.ts b/src/data-structures/binary-tree/binary-tree.ts index dba3d8f..0b7c6ea 100644 --- a/src/data-structures/binary-tree/binary-tree.ts +++ b/src/data-structures/binary-tree/binary-tree.ts @@ -30,15 +30,15 @@ export enum LoopType { iterative = 1, recursive = 2} export class BinaryTreeNode { - protected _id: BinaryTreeNodeId; - get id(): BinaryTreeNodeId { - return this._id; + constructor(id: BinaryTreeNodeId, val: T, count?: number) { + this._id = id; + this._val = val; + this._count = count ?? 1; } - /** - * Starting from TypeScript version 5.0 and onwards, the use of distinct access modifiers for Getters and Setters is not permitted. As an alternative, to ensure compatibility, it is necessary to adopt a Java-style approach for Setters (using the same name as the property) while utilizing separate method names for Getters. - */ - getId(): BinaryTreeNodeId { + protected _id: BinaryTreeNodeId; + + get id(): BinaryTreeNodeId { return this._id; } @@ -51,26 +51,13 @@ export class BinaryTreeNode { return this._val; } - /** - * Starting from TypeScript version 5.0 and onwards, the use of distinct access modifiers for Getters and Setters is not permitted. As an alternative, to ensure compatibility, it is necessary to adopt a Java-style approach for Setters (using the same name as the property) while utilizing separate method names for Getters. - */ - getVal(): T { - return this._val; - } - set val(v: T) { this._val = v; } protected _left?: BinaryTreeNode | null; - get left(): BinaryTreeNode | null | undefined { - return this._left; - } - /** - * Starting from TypeScript version 5.0 and onwards, the use of distinct access modifiers for Getters and Setters is not permitted. As an alternative, to ensure compatibility, it is necessary to adopt a Java-style approach for Setters (using the same name as the property) while utilizing separate method names for Getters. - */ - getLeft(): BinaryTreeNode | null | undefined { + get left(): BinaryTreeNode | null | undefined { return this._left; } @@ -83,14 +70,8 @@ export class BinaryTreeNode { } protected _right?: BinaryTreeNode | null; - get right(): BinaryTreeNode | null | undefined { - return this._right; - } - /** - * Starting from TypeScript version 5.0 and onwards, the use of distinct access modifiers for Getters and Setters is not permitted. As an alternative, to ensure compatibility, it is necessary to adopt a Java-style approach for Setters (using the same name as the property) while utilizing separate method names for Getters. - */ - getRight(): BinaryTreeNode | null | undefined { + get right(): BinaryTreeNode | null | undefined { return this._right; } @@ -103,10 +84,73 @@ export class BinaryTreeNode { } protected _parent: BinaryTreeNode | null | undefined; + get parent(): BinaryTreeNode | null | undefined { return this._parent; } + set parent(v: BinaryTreeNode | null | undefined) { + this._parent = v; + } + + protected _familyPosition: FamilyPosition = FamilyPosition.root; + + get familyPosition(): FamilyPosition { + return this._familyPosition; + } + + set familyPosition(v: FamilyPosition) { + this._familyPosition = v; + } + + protected _count = 1; + + get count(): number { + return this._count; + } + + set count(v: number) { + this._count = v; + } + + protected _height = 0; + + get height(): number { + return this._height; + } + + set height(v: number) { + this._height = v; + } + + /** + * Starting from TypeScript version 5.0 and onwards, the use of distinct access modifiers for Getters and Setters is not permitted. As an alternative, to ensure compatibility, it is necessary to adopt a Java-style approach for Setters (using the same name as the property) while utilizing separate method names for Getters. + */ + getId(): BinaryTreeNodeId { + return this._id; + } + + /** + * Starting from TypeScript version 5.0 and onwards, the use of distinct access modifiers for Getters and Setters is not permitted. As an alternative, to ensure compatibility, it is necessary to adopt a Java-style approach for Setters (using the same name as the property) while utilizing separate method names for Getters. + */ + getVal(): T { + return this._val; + } + + /** + * Starting from TypeScript version 5.0 and onwards, the use of distinct access modifiers for Getters and Setters is not permitted. As an alternative, to ensure compatibility, it is necessary to adopt a Java-style approach for Setters (using the same name as the property) while utilizing separate method names for Getters. + */ + getLeft(): BinaryTreeNode | null | undefined { + return this._left; + } + + /** + * Starting from TypeScript version 5.0 and onwards, the use of distinct access modifiers for Getters and Setters is not permitted. As an alternative, to ensure compatibility, it is necessary to adopt a Java-style approach for Setters (using the same name as the property) while utilizing separate method names for Getters. + */ + getRight(): BinaryTreeNode | null | undefined { + return this._right; + } + /** * Starting from TypeScript version 5.0 and onwards, the use of distinct access modifiers for Getters and Setters is not permitted. As an alternative, to ensure compatibility, it is necessary to adopt a Java-style approach for Setters (using the same name as the property) while utilizing separate method names for Getters. */ @@ -114,15 +158,6 @@ export class BinaryTreeNode { return this._parent; } - set parent(v: BinaryTreeNode | null | undefined) { - this._parent = v; - } - - protected _familyPosition: FamilyPosition = FamilyPosition.root; - get familyPosition(): FamilyPosition { - return this._familyPosition; - } - /** * Starting from TypeScript version 5.0 and onwards, the use of distinct access modifiers for Getters and Setters is not permitted. As an alternative, to ensure compatibility, it is necessary to adopt a Java-style approach for Setters (using the same name as the property) while utilizing separate method names for Getters. */ @@ -130,15 +165,6 @@ export class BinaryTreeNode { return this._familyPosition; } - set familyPosition(v: FamilyPosition) { - this._familyPosition = v; - } - - protected _count = 1; - get count(): number { - return this._count; - } - /** * Starting from TypeScript version 5.0 and onwards, the use of distinct access modifiers for Getters and Setters is not permitted. As an alternative, to ensure compatibility, it is necessary to adopt a Java-style approach for Setters (using the same name as the property) while utilizing separate method names for Getters. */ @@ -146,15 +172,6 @@ export class BinaryTreeNode { return this._count; } - set count(v: number) { - this._count = v; - } - - protected _height = 0; - get height(): number { - return this._height; - } - /** * Starting from TypeScript version 5.0 and onwards, the use of distinct access modifiers for Getters and Setters is not permitted. As an alternative, to ensure compatibility, it is necessary to adopt a Java-style approach for Setters (using the same name as the property) while utilizing separate method names for Getters. */ @@ -162,16 +179,6 @@ export class BinaryTreeNode { return this._height; } - set height(v: number) { - this._height = v; - } - - constructor(id: BinaryTreeNodeId, val: T, count?: number) { - this._id = id; - this._val = val; - this._count = count ?? 1; - } - swapLocation(swapNode: BinaryTreeNode): BinaryTreeNode { const {val, count, height} = swapNode; const tempNode = new BinaryTreeNode(swapNode.id, val); @@ -235,14 +242,6 @@ export class BinaryTree { return this._root; } - /** - * Starting from TypeScript version 5.0 and onwards, the use of distinct access modifiers for Getters and Setters is not permitted. As an alternative, to ensure compatibility, it is necessary to adopt a Java-style approach for Getters (using the same name as the property) while utilizing separate method names for Setters. - * @returns The method is returning either a BinaryTreeNode object of type T or null. - */ - getRoot(): BinaryTreeNode | null { - return this._root; - } - protected set root(v: BinaryTreeNode | null) { if (v) { v.parent = null; @@ -257,13 +256,6 @@ export class BinaryTree { return this._size; } - /** - * Starting from TypeScript version 5.0 and onwards, the use of distinct access modifiers for Getters and Setters is not permitted. As an alternative, to ensure compatibility, it is necessary to adopt a Java-style approach for Setters (using the same name as the property) while utilizing separate method names for Getters. - */ - getSize(): number { - return this._size; - } - protected set size(v: number) { this._size = v; } @@ -274,6 +266,25 @@ export class BinaryTree { return this._count; } + protected set count(v: number) { + this._count = v; + } + + /** + * Starting from TypeScript version 5.0 and onwards, the use of distinct access modifiers for Getters and Setters is not permitted. As an alternative, to ensure compatibility, it is necessary to adopt a Java-style approach for Getters (using the same name as the property) while utilizing separate method names for Setters. + * @returns The method is returning either a BinaryTreeNode object of type T or null. + */ + getRoot(): BinaryTreeNode | null { + return this._root; + } + + /** + * Starting from TypeScript version 5.0 and onwards, the use of distinct access modifiers for Getters and Setters is not permitted. As an alternative, to ensure compatibility, it is necessary to adopt a Java-style approach for Setters (using the same name as the property) while utilizing separate method names for Getters. + */ + getSize(): number { + return this._size; + } + /** * Starting from TypeScript version 5.0 and onwards, the use of distinct access modifiers for Getters and Setters is not permitted. As an alternative, to ensure compatibility, it is necessary to adopt a Java-style approach for Setters (using the same name as the property) while utilizing separate method names for Getters. */ @@ -281,10 +292,6 @@ export class BinaryTree { return this._count; } - protected set count(v: number) { - this._count = v; - } - /** * The function creates a new binary tree node with the given id, value, and count, or returns null if the value is * null. diff --git a/src/data-structures/binary-tree/segment-tree.ts b/src/data-structures/binary-tree/segment-tree.ts index 83d9afc..13268fe 100644 --- a/src/data-structures/binary-tree/segment-tree.ts +++ b/src/data-structures/binary-tree/segment-tree.ts @@ -20,85 +20,102 @@ export class SegmentTreeNode { get start(): number { return this._start; } + + set start(v: number) { + this._start = v; + } + + protected _end = 0; + + get end(): number { + return this._end; + } + + set end(v: number) { + this._end = v; + } + + protected _val: SegmentTreeNodeVal | null = null; + + get val(): SegmentTreeNodeVal | null { + return this._val; + } + + set val(v: SegmentTreeNodeVal | null) { + this._val = v; + } + + protected _sum = 0; + + get sum(): number { + return this._sum; + } + + set sum(v: number) { + this._sum = v; + } + + protected _left: SegmentTreeNode | null = null; + + get left(): SegmentTreeNode | null { + return this._left; + } + + set left(v: SegmentTreeNode | null) { + this._left = v; + } + + protected _right: SegmentTreeNode | null = null; + + get right(): SegmentTreeNode | null { + return this._right; + } + + set right(v: SegmentTreeNode | null) { + this._right = v; + } + /** * Starting from TypeScript version 5.0 and onwards, the use of distinct access modifiers for Getters and Setters is not permitted. As an alternative, to ensure compatibility, it is necessary to adopt a Java-style approach for Setters (using the same name as the property) while utilizing separate method names for Getters. */ getStart(): number { return this._start; } - set start(v: number) { - this._start = v; - } - protected _end = 0; - get end(): number { - return this._end; - } /** * Starting from TypeScript version 5.0 and onwards, the use of distinct access modifiers for Getters and Setters is not permitted. As an alternative, to ensure compatibility, it is necessary to adopt a Java-style approach for Setters (using the same name as the property) while utilizing separate method names for Getters. */ getEnd(): number { return this._end; } - set end(v: number) { - this._end = v; - } - protected _val: SegmentTreeNodeVal | null = null; - get val(): SegmentTreeNodeVal | null { - return this._val; - } /** * Starting from TypeScript version 5.0 and onwards, the use of distinct access modifiers for Getters and Setters is not permitted. As an alternative, to ensure compatibility, it is necessary to adopt a Java-style approach for Setters (using the same name as the property) while utilizing separate method names for Getters. */ getVal(): SegmentTreeNodeVal | null { return this._val; } - set val(v: SegmentTreeNodeVal | null) { - this._val = v; - } - protected _sum = 0; - get sum(): number { - return this._sum; - } /** * Starting from TypeScript version 5.0 and onwards, the use of distinct access modifiers for Getters and Setters is not permitted. As an alternative, to ensure compatibility, it is necessary to adopt a Java-style approach for Setters (using the same name as the property) while utilizing separate method names for Getters. */ getSum(): number { return this._sum; } - set sum(v: number) { - this._sum = v; - } - protected _left: SegmentTreeNode | null = null; - get left(): SegmentTreeNode | null { - return this._left; - } /** * Starting from TypeScript version 5.0 and onwards, the use of distinct access modifiers for Getters and Setters is not permitted. As an alternative, to ensure compatibility, it is necessary to adopt a Java-style approach for Setters (using the same name as the property) while utilizing separate method names for Getters. */ getLeft(): SegmentTreeNode | null { return this._left; } - set left(v: SegmentTreeNode | null) { - this._left = v; - } - protected _right: SegmentTreeNode | null = null; - get right(): SegmentTreeNode | null { - return this._right; - } /** * Starting from TypeScript version 5.0 and onwards, the use of distinct access modifiers for Getters and Setters is not permitted. As an alternative, to ensure compatibility, it is necessary to adopt a Java-style approach for Setters (using the same name as the property) while utilizing separate method names for Getters. */ getRight(): SegmentTreeNode | null { return this._right; } - set right(v: SegmentTreeNode | null) { - this._right = v; - } } export class SegmentTree { @@ -128,15 +145,17 @@ export class SegmentTree { get root(): SegmentTreeNode | null { return this._root; } + + set root(v: SegmentTreeNode | null) { + this._root = v; + } + /** * Starting from TypeScript version 5.0 and onwards, the use of distinct access modifiers for Getters and Setters is not permitted. As an alternative, to ensure compatibility, it is necessary to adopt a Java-style approach for Setters (using the same name as the property) while utilizing separate method names for Getters. */ getRoot(): SegmentTreeNode | null { return this._root; } - set root(v: SegmentTreeNode | null) { - this._root = v; - } /** * The function builds a segment tree by recursively dividing the given range into smaller segments and creating nodes diff --git a/src/data-structures/graph/abstract-graph.ts b/src/data-structures/graph/abstract-graph.ts index 59ac1b8..0581f70 100644 --- a/src/data-structures/graph/abstract-graph.ts +++ b/src/data-structures/graph/abstract-graph.ts @@ -10,15 +10,13 @@ import {PriorityQueue} from '../priority-queue'; import type {DijkstraResult, IGraph, VertexId} from '../types'; export class AbstractVertex { - protected _id: VertexId; - get id(): VertexId { - return this._id; + constructor(id: VertexId) { + this._id = id; } - /** - * Starting from TypeScript version 5.0 and onwards, the use of distinct access modifiers for Getters and Setters is not permitted. As an alternative, to ensure compatibility, it is necessary to adopt a Java-style approach for Setters (using the same name as the property) while utilizing separate method names for Getters. - */ - getId(): VertexId { + protected _id: VertexId; + + get id(): VertexId { return this._id; } @@ -26,8 +24,11 @@ export class AbstractVertex { this._id = v; } - constructor(id: VertexId) { - this._id = id; + /** + * Starting from TypeScript version 5.0 and onwards, the use of distinct access modifiers for Getters and Setters is not permitted. As an alternative, to ensure compatibility, it is necessary to adopt a Java-style approach for Setters (using the same name as the property) while utilizing separate method names for Getters. + */ + getId(): VertexId { + return this._id; } } @@ -51,6 +52,20 @@ export abstract class AbstractEdge { return this._weight; } + set weight(v: number) { + this._weight = v; + } + + private _hashCode: string; + + get hashCode(): string { + return this._hashCode; + } + + set hashCode(v: string) { + this._hashCode = v; + } + /** * Starting from TypeScript version 5.0 and onwards, the use of distinct access modifiers for Getters and Setters is not permitted. As an alternative, to ensure compatibility, it is necessary to adopt a Java-style approach for Setters (using the same name as the property) while utilizing separate method names for Getters. */ @@ -58,25 +73,12 @@ export abstract class AbstractEdge { return this._weight; } - set weight(v: number) { - this._weight = v; - } - - private _hashCode: string; - get hashCode(): string { - return this._hashCode; - } - /** * Starting from TypeScript version 5.0 and onwards, the use of distinct access modifiers for Getters and Setters is not permitted. As an alternative, to ensure compatibility, it is necessary to adopt a Java-style approach for Setters (using the same name as the property) while utilizing separate method names for Getters. */ getHashCode(): string { return this._hashCode; } - - set hashCode(v: string) { - this._hashCode = v; - } } // Connected Component === Largest Connected Sub-Graph diff --git a/src/data-structures/graph/directed-graph.ts b/src/data-structures/graph/directed-graph.ts index 8ba807c..e76876a 100644 --- a/src/data-structures/graph/directed-graph.ts +++ b/src/data-structures/graph/directed-graph.ts @@ -40,29 +40,34 @@ export class DirectedEdge extends AbstractEdge { get src(): VertexId { return this._src; } + + set src(v: VertexId) { + this._src = v; + } + + private _dest: VertexId; + + get dest(): VertexId { + return this._dest; + } + + set dest(v: VertexId) { + this._dest = v; + } + /** * Starting from TypeScript version 5.0 and onwards, the use of distinct access modifiers for Getters and Setters is not permitted. As an alternative, to ensure compatibility, it is necessary to adopt a Java-style approach for Setters (using the same name as the property) while utilizing separate method names for Getters. */ getSrc(): VertexId { return this._src; } - set src(v: VertexId) { - this._src = v; - } - private _dest: VertexId; - get dest(): VertexId { - return this._dest; - } /** * Starting from TypeScript version 5.0 and onwards, the use of distinct access modifiers for Getters and Setters is not permitted. As an alternative, to ensure compatibility, it is necessary to adopt a Java-style approach for Setters (using the same name as the property) while utilizing separate method names for Getters. */ getDest(): VertexId { return this._dest; } - set dest(v: VertexId) { - this._dest = v; - } } // Strongly connected, One direction connected, Weakly connected @@ -159,14 +164,14 @@ export class DirectedGraph ext const srcOutEdges = this._outEdgeMap.get(src); if (srcOutEdges) { - /** - * The removeEdge function removes an edge from a graph and returns the removed edge, or null if the edge was not - * found. - * @param {E} edge - The `edge` parameter represents the edge that you want to remove from the graph. It should be an - * object that has `src` and `dest` properties, which represent the source and destination vertices of the edge, - * respectively. - * @returns The method `removeEdge` returns the removed edge (`E`) if it exists, or `null` if the edge does not exist. - */ + /** + * The removeEdge function removes an edge from a graph and returns the removed edge, or null if the edge was not + * found. + * @param {E} edge - The `edge` parameter represents the edge that you want to remove from the graph. It should be an + * object that has `src` and `dest` properties, which represent the source and destination vertices of the edge, + * respectively. + * @returns The method `removeEdge` returns the removed edge (`E`) if it exists, or `null` if the edge does not exist. + */ arrayRemove(srcOutEdges, (edge: DirectedEdge) => edge.dest === dest.id); } @@ -184,7 +189,7 @@ export class DirectedGraph ext * and `dest`, which represent the source and destination vertices of the edge, respectively. * @returns The method `removeEdge` returns the removed edge (`E`) if it exists, or `null` if the edge does not exist. */ - removeEdge(edge: E ): E | null { + removeEdge(edge: E): E | null { let removed: E | null = null; const src = this.getVertex(edge.src); const dest = this.getVertex(edge.dest); diff --git a/src/data-structures/graph/undirected-graph.ts b/src/data-structures/graph/undirected-graph.ts index 430db58..67623d2 100644 --- a/src/data-structures/graph/undirected-graph.ts +++ b/src/data-structures/graph/undirected-graph.ts @@ -38,36 +38,41 @@ export class UndirectedEdge extends AbstractEdge { get vertices() { return this._vertices; } + + set vertices(v: [VertexId, VertexId]) { + this._vertices = v; + } + /** * Starting from TypeScript version 5.0 and onwards, the use of distinct access modifiers for Getters and Setters is not permitted. As an alternative, to ensure compatibility, it is necessary to adopt a Java-style approach for Setters (using the same name as the property) while utilizing separate method names for Getters. */ getVertices() { return this._vertices; } - set vertices(v: [VertexId, VertexId]) { - this._vertices = v; - } } export class UndirectedGraph extends AbstractGraph { + constructor() { + super(); + this._edges = new Map(); + } + protected _edges: Map; + get edges(): Map { return this._edges; } + + protected set edges(v: Map) { + this._edges = v; + } + /** * Starting from TypeScript version 5.0 and onwards, the use of distinct access modifiers for Getters and Setters is not permitted. As an alternative, to ensure compatibility, it is necessary to adopt a Java-style approach for Setters (using the same name as the property) while utilizing separate method names for Getters. */ getEdges(): Map { return this._edges; } - protected set edges(v: Map) { - this._edges = v; - } - - constructor() { - super(); - this._edges = new Map(); - } /** * The function `getEdge` returns the first edge that connects two vertices, or null if no such edge exists. diff --git a/src/data-structures/hash/coordinate-map.ts b/src/data-structures/hash/coordinate-map.ts index def0778..788cb47 100644 --- a/src/data-structures/hash/coordinate-map.ts +++ b/src/data-structures/hash/coordinate-map.ts @@ -6,24 +6,27 @@ * @license MIT License */ export class CoordinateMap extends Map { + constructor(joint?: string) { + super(); + if (joint !== undefined) this._joint = joint; + } + protected _joint: string = '_'; + get joint(): string { return this._joint; } + + protected set joint(v: string) { + this._joint = v; + } + /** * Starting from TypeScript version 5.0 and onwards, the use of distinct access modifiers for Getters and Setters is not permitted. As an alternative, to ensure compatibility, it is necessary to adopt a Java-style approach for Setters (using the same name as the property) while utilizing separate method names for Getters. */ getJoint(): string { return this._joint; } - protected set joint(v: string) { - this._joint = v; - } - - constructor(joint?: string) { - super(); - if (joint !== undefined) this._joint = joint; - } /** * The "has" function overrides the base class's "has" function and checks if a key exists in the map by joining the diff --git a/src/data-structures/hash/coordinate-set.ts b/src/data-structures/hash/coordinate-set.ts index 9245ebd..d5d1011 100644 --- a/src/data-structures/hash/coordinate-set.ts +++ b/src/data-structures/hash/coordinate-set.ts @@ -6,24 +6,27 @@ * @license MIT License */ export class CoordinateSet extends Set { + constructor(joint?: string) { + super(); + if (joint !== undefined) this._joint = joint; + } + protected _joint: string = '_'; + get joint(): string { return this._joint; } + + protected set joint(v: string) { + this._joint = v; + } + /** * Starting from TypeScript version 5.0 and onwards, the use of distinct access modifiers for Getters and Setters is not permitted. As an alternative, to ensure compatibility, it is necessary to adopt a Java-style approach for Setters (using the same name as the property) while utilizing separate method names for Getters. */ getJoint(): string { return this._joint; } - protected set joint(v: string) { - this._joint = v; - } - - constructor(joint?: string) { - super(); - if (joint !== undefined) this._joint = joint; - } /** * The "has" function overrides the "has" method of the superclass and checks if a value exists in an array after diff --git a/src/data-structures/heap/heap.ts b/src/data-structures/heap/heap.ts index 17a2c29..6a00b8f 100644 --- a/src/data-structures/heap/heap.ts +++ b/src/data-structures/heap/heap.ts @@ -9,34 +9,6 @@ import {PriorityQueue} from '../priority-queue'; import type {HeapItem, HeapOptions} from '../types'; export abstract class Heap { - protected abstract _pq: PriorityQueue>; - get pq() { - return this._pq; - } - /** - * Starting from TypeScript version 5.0 and onwards, the use of distinct access modifiers for Getters and Setters is not permitted. As an alternative, to ensure compatibility, it is necessary to adopt a Java-style approach for Setters (using the same name as the property) while utilizing separate method names for Getters. - */ - getPq() { - return this._pq; - } - protected set pq(v: PriorityQueue>) { - this._pq = v; - } - - protected _priorityCb: (element: T) => number; - get priorityCb() { - return this._priorityCb; - } - /** - * Starting from TypeScript version 5.0 and onwards, the use of distinct access modifiers for Getters and Setters is not permitted. As an alternative, to ensure compatibility, it is necessary to adopt a Java-style approach for Setters (using the same name as the property) while utilizing separate method names for Getters. - */ - getPriorityCb() { - return this._priorityCb; - } - protected set priorityCb(v: (element: T) => number) { - this._priorityCb = v; - } - /** * The function is a constructor for a class that initializes a priority callback function based on the * options provided. @@ -54,6 +26,25 @@ export abstract class Heap { } } + protected abstract _pq: PriorityQueue>; + + get pq() { + return this._pq; + } + + protected set pq(v: PriorityQueue>) { + this._pq = v; + } + + protected _priorityCb: (element: T) => number; + get priorityCb() { + return this._priorityCb; + } + + protected set priorityCb(v: (element: T) => number) { + this._priorityCb = v; + } + /** * The function returns the size of a priority queue. * @returns The size of the priority queue. @@ -61,6 +52,21 @@ export abstract class Heap { get size(): number { return this._pq.size; } + + /** + * Starting from TypeScript version 5.0 and onwards, the use of distinct access modifiers for Getters and Setters is not permitted. As an alternative, to ensure compatibility, it is necessary to adopt a Java-style approach for Setters (using the same name as the property) while utilizing separate method names for Getters. + */ + getPq() { + return this._pq; + } + + /** + * Starting from TypeScript version 5.0 and onwards, the use of distinct access modifiers for Getters and Setters is not permitted. As an alternative, to ensure compatibility, it is necessary to adopt a Java-style approach for Setters (using the same name as the property) while utilizing separate method names for Getters. + */ + getPriorityCb() { + return this._priorityCb; + } + /** * Starting from TypeScript version 5.0 and onwards, the use of distinct access modifiers for Getters and Setters is not permitted. As an alternative, to ensure compatibility, it is necessary to adopt a Java-style approach for Setters (using the same name as the property) while utilizing separate method names for Getters. */ diff --git a/src/data-structures/linked-list/doubly-linked-list.ts b/src/data-structures/linked-list/doubly-linked-list.ts index 8da9a84..4d0a9c3 100644 --- a/src/data-structures/linked-list/doubly-linked-list.ts +++ b/src/data-structures/linked-list/doubly-linked-list.ts @@ -8,48 +8,56 @@ import type {DoublyLinkedListGetBy} from '../types'; export class DoublyLinkedListNode { - protected _val: T; - get val(): T { - return this._val; - } - set val(v: T) { - this._val = v; - } - - protected _next: DoublyLinkedListNode | null; - get next(): DoublyLinkedListNode | null { - return this._next; - } - set next(v: DoublyLinkedListNode | null) { - this._next = v; - } - - protected _prev: DoublyLinkedListNode | null; - get prev(): DoublyLinkedListNode | null { - return this._prev; - } - set prev(v: DoublyLinkedListNode | null) { - this._prev = v; - } - constructor(nodeValue: T) { this._val = nodeValue; this._next = null; this._prev = null; } + + protected _val: T; + + get val(): T { + return this._val; + } + + set val(v: T) { + this._val = v; + } + + protected _next: DoublyLinkedListNode | null; + + get next(): DoublyLinkedListNode | null { + return this._next; + } + + set next(v: DoublyLinkedListNode | null) { + this._next = v; + } + + protected _prev: DoublyLinkedListNode | null; + + get prev(): DoublyLinkedListNode | null { + return this._prev; + } + + set prev(v: DoublyLinkedListNode | null) { + this._prev = v; + } } export class DoublyLinkedList { + constructor() { + this._first = null; + this._last = null; + this._size = 0; + } + protected _first: DoublyLinkedListNode | null; + get first(): DoublyLinkedListNode | null { return this._first; } - /** - * Starting from TypeScript version 5.0 and onwards, the use of distinct access modifiers for Getters and Setters is not permitted. As an alternative, to ensure compatibility, it is necessary to adopt a Java-style approach for Setters (using the same name as the property) while utilizing separate method names for Getters. - */ - getFirst(): DoublyLinkedListNode | null { - return this._first; - } + protected set first(v: DoublyLinkedListNode | null) { this._first = v; } @@ -58,35 +66,41 @@ export class DoublyLinkedList { get last(): DoublyLinkedListNode | null { return this._last; } + + protected set last(v: DoublyLinkedListNode | null) { + this._last = v; + } + + protected _size: number; + + get size(): number { + return this._size; + } + + protected set size(v: number) { + this._size = v; + } + + /** + * Starting from TypeScript version 5.0 and onwards, the use of distinct access modifiers for Getters and Setters is not permitted. As an alternative, to ensure compatibility, it is necessary to adopt a Java-style approach for Setters (using the same name as the property) while utilizing separate method names for Getters. + */ + getFirst(): DoublyLinkedListNode | null { + return this._first; + } + /** * Starting from TypeScript version 5.0 and onwards, the use of distinct access modifiers for Getters and Setters is not permitted. As an alternative, to ensure compatibility, it is necessary to adopt a Java-style approach for Setters (using the same name as the property) while utilizing separate method names for Getters. */ getLast(): DoublyLinkedListNode | null { return this._last; } - protected set last(v: DoublyLinkedListNode | null) { - this._last = v; - } - protected _size: number; - get size(): number { - return this._size; - } /** * Starting from TypeScript version 5.0 and onwards, the use of distinct access modifiers for Getters and Setters is not permitted. As an alternative, to ensure compatibility, it is necessary to adopt a Java-style approach for Setters (using the same name as the property) while utilizing separate method names for Getters. */ getSize(): number { return this._size; } - protected set size(v: number) { - this._size = v; - } - - constructor() { - this._first = null; - this._last = null; - this._size = 0; - } /** * The function adds a new node with a given value to the beginning of a doubly linked list. diff --git a/src/data-structures/linked-list/singly-linked-list.ts b/src/data-structures/linked-list/singly-linked-list.ts index b1ab03f..7527fac 100644 --- a/src/data-structures/linked-list/singly-linked-list.ts +++ b/src/data-structures/linked-list/singly-linked-list.ts @@ -10,7 +10,15 @@ /* The SinglyLinkedListNode class represents a node in a singly linked list and provides methods for inserting, removing, and accessing nodes. */ export class SinglyLinkedListNode { + constructor(val: NodeVal, prev?: SinglyLinkedListNode | null, next?: SinglyLinkedListNode | null, list?: SinglyLinkedList | null) { + this._val = val; + this._prev = prev || null; + this._next = next || null; + this._list = list || null; + } + protected _val: NodeVal; + get val(): NodeVal { return this._val; } @@ -20,6 +28,7 @@ export class SinglyLinkedListNode { } protected _prev: SinglyLinkedListNode | null; + get prev(): SinglyLinkedListNode | null { return this._prev; } @@ -29,6 +38,7 @@ export class SinglyLinkedListNode { } protected _next: SinglyLinkedListNode | null + get next(): SinglyLinkedListNode | null { return this._next; } @@ -38,6 +48,7 @@ export class SinglyLinkedListNode { } protected _list: SinglyLinkedList | null + get list(): SinglyLinkedList | null { return this._list; } @@ -46,13 +57,6 @@ export class SinglyLinkedListNode { this._list = value; } - constructor(val: NodeVal, prev?: SinglyLinkedListNode | null, next?: SinglyLinkedListNode | null, list?: SinglyLinkedList | null) { - this._val = val; - this._prev = prev || null; - this._next = next || null; - this._list = list || null; - } - get index() { if (!this.list) { return undefined; @@ -97,31 +101,6 @@ export class SinglyLinkedListNode { export class SinglyLinkedList { - protected _head: SinglyLinkedListNode | null; - get head(): SinglyLinkedListNode | null { - return this._head; - } - set head(value: SinglyLinkedListNode | null) { - this._head = value; - } - - - protected _tail: SinglyLinkedListNode | null; - get tail(): SinglyLinkedListNode | null { - return this._tail; - } - set tail(value: SinglyLinkedListNode | null) { - this._tail = value; - } - - protected _size: number; - get size(): number { - return this._size; - } - set size(value: number) { - this._size = value; - } - /** * The constructor initializes a linked list with the given arguments as nodes. * @param {NodeVal[]} args - args is a rest parameter that allows the constructor to accept an arbitrary number of @@ -137,6 +116,36 @@ export class SinglyLinkedList { } } + protected _head: SinglyLinkedListNode | null; + + get head(): SinglyLinkedListNode | null { + return this._head; + } + + set head(value: SinglyLinkedListNode | null) { + this._head = value; + } + + protected _tail: SinglyLinkedListNode | null; + + get tail(): SinglyLinkedListNode | null { + return this._tail; + } + + set tail(value: SinglyLinkedListNode | null) { + this._tail = value; + } + + protected _size: number; + + get size(): number { + return this._size; + } + + set size(value: number) { + this._size = value; + } + /** * The `from` function in TypeScript creates a new SinglyLinkedList instance from an iterable object. * @param iterable - The `iterable` parameter is an object that can be iterated over, such as an array or a string. It diff --git a/src/data-structures/priority-queue/priority-queue.ts b/src/data-structures/priority-queue/priority-queue.ts index 6a8ab92..2a991cd 100644 --- a/src/data-structures/priority-queue/priority-queue.ts +++ b/src/data-structures/priority-queue/priority-queue.ts @@ -9,20 +9,6 @@ import type {PriorityQueueComparator, PriorityQueueDFSOrderPattern, PriorityQueu export class PriorityQueue { - protected _nodes: T[] = []; - get nodes(): T[] { - return this._nodes; - } - /** - * Starting from TypeScript version 5.0 and onwards, the use of distinct access modifiers for Getters and Setters is not permitted. As an alternative, to ensure compatibility, it is necessary to adopt a Java-style approach for Setters (using the same name as the property) while utilizing separate method names for Getters. - */ - getNodes(): T[] { - return this._nodes; - } - protected set nodes(value: T[]) { - this._nodes = value; - } - /** * The constructor initializes a priority queue with the given options, including an array of nodes and a comparator * function. @@ -39,6 +25,16 @@ export class PriorityQueue { } } + protected _nodes: T[] = []; + + get nodes(): T[] { + return this._nodes; + } + + protected set nodes(value: T[]) { + this._nodes = value; + } + get size(): number { return this.nodes.length; } @@ -67,6 +63,13 @@ export class PriorityQueue { return new PriorityQueue({...options, isFix: true}).isValid(); } + /** + * Starting from TypeScript version 5.0 and onwards, the use of distinct access modifiers for Getters and Setters is not permitted. As an alternative, to ensure compatibility, it is necessary to adopt a Java-style approach for Setters (using the same name as the property) while utilizing separate method names for Getters. + */ + getNodes(): T[] { + return this._nodes; + } + /** * The "add" function adds a node to the heap and ensures that the heap property is maintained. * @param {T} node - The parameter "node" is of type T, which means it can be any data type. It represents the node diff --git a/src/data-structures/queue/deque.ts b/src/data-structures/queue/deque.ts index ff535d3..0190442 100644 --- a/src/data-structures/queue/deque.ts +++ b/src/data-structures/queue/deque.ts @@ -17,50 +17,60 @@ export class Deque extends DoublyLinkedList { // O(n) time complexity of adding at the beginning and the end // todo tested slowest one export class ObjectDeque { + constructor(capacity?: number) { + if (capacity !== undefined) this._capacity = capacity; + } + private _nodes: { [key: number]: T } = {}; + get nodes(): { [p: number]: T } { return this._nodes; } + protected set nodes(value: { [p: number]: T }) { this._nodes = value; } private _capacity = Number.MAX_SAFE_INTEGER; + get capacity(): number { return this._capacity; } + set capacity(value: number) { this._capacity = value; } private _first: number = -1; + get first(): number { return this._first; } + set first(value: number) { this._first = value; } private _last: number = -1; + get last(): number { return this._last; } + set last(value: number) { this._last = value; } private _size: number = 0; + get size(): number { return this._size; } + protected set size(value: number) { this._size = value; } - constructor(capacity?: number) { - if (capacity !== undefined) this._capacity = capacity; - } - addFirst(value: T) { if (this._size === 0) { const mid = Math.floor(this._capacity / 2); diff --git a/src/utils/types/utils.ts b/src/utils/types/utils.ts index a683bf1..37d3ea3 100644 --- a/src/utils/types/utils.ts +++ b/src/utils/types/utils.ts @@ -1,178 +1,4 @@ -export type JSONSerializable = { - [key: string]: any -} -export type JSONValue = string | number | boolean | undefined | JSONObject; - -export interface JSONObject { - [key: string]: JSONValue; -} - -export type AnyFunction = (...args: A) => R; -export type Primitive = - | number - | string - | boolean - | symbol - | undefined - | null - | void - | AnyFunction - | Date; - -export type Cast = { [M in keyof TComplex]: T }; - - -export type DeepLeavesWrap = - T extends string ? Cast - : T extends number ? Cast - : T extends boolean ? Cast - : T extends undefined ? Cast - : T extends null ? Cast - : T extends void ? Cast - : T extends symbol ? Cast - : T extends AnyFunction ? Cast - : T extends Date ? Cast - : { - [K in keyof T]: - T[K] extends (infer U)[] ? DeepLeavesWrap[] - : DeepLeavesWrap; - } - - -type Json = null | string | number | boolean | Json [] | { [name: string]: Json } - -export type TypeName = T extends string - ? 'string' - : T extends number - ? 'number' - : T extends boolean - ? 'boolean' - : T extends undefined - ? 'undefined' - : T extends AnyFunction - ? 'function' - : 'object'; - -export type JsonKeys = keyof { - [P in keyof T]: number -} - -const arr = ['1', 2, 4, 5, 6] as const; -type Range = typeof arr[number]; -const a: Range = 2; - - -/** - * A function that emits a side effect and does not return anything. - */ -export type Procedure = (...args: any[]) => void; - -export type DebounceOptions = { - isImmediate?: boolean; - maxWait?: number; -}; - -export interface DebouncedFunction { - cancel: () => void; - - (this: ThisParameterType, ...args: [...Parameters]): void; -} - -export type MonthKey = - 'January' | - 'February' | - 'March' | - 'April' | - 'May' | - 'June' | - 'July' | - 'August' | - 'September' | - 'October' | - 'November' | - 'December'; - -export type Month = { [key in MonthKey]: string } - -export type UnionToIntersection = (U extends any ? (k: U) => void : never) extends ((k: infer I) => void) ? I : never; - -export class TreeNode { - id: string; - name?: string | undefined; - value?: T | undefined; - children?: TreeNode[] | undefined; - - constructor(id: string, name?: string, value?: T, children?: TreeNode[]) { - this.id = id; - this.name = name || ''; - this.value = value || undefined; - this.children = children || []; - } - - // TODO get set - // get name (): string | undefined { - // return this.name; - // } - // - // set name (name: string | undefined) { - // this.name = name; - // } - - addChildren(children: TreeNode | TreeNode []) { - if (!this.children) { - this.children = []; - } - if (children instanceof TreeNode) { - this.children.push(children); - } else { - this.children = this.children.concat(children); - } - } - - getHeight() { - // eslint-disable-next-line @typescript-eslint/no-this-alias - const beginRoot = this; - let maxDepth = 1; - if (beginRoot) { - const bfs = (node: TreeNode, level: number) => { - if (level > maxDepth) { - maxDepth = level; - } - const {children} = node; - if (children) { - for (let i = 0, len = children.length; i < len; i++) { - bfs(children[i], level + 1); - } - } - }; - bfs(beginRoot, 1); - } - return maxDepth; - } - -} - -export type OrderType = 'InOrder' | 'PreOrder' | 'PostOrder' - -export type DeepProxy = T extends (...args: any[]) => infer R - ? (...args: [...Parameters]) => DeepProxy - : T extends object - ? { [K in keyof T]: DeepProxy } - : T; - -export type DeepProxyOnChange = (target: any, property: string | symbol, value: any, receiver: any, descriptor: any, result: any) => void; - -export type DeepProxyOnGet = (target: any, property: string | symbol, value: any, receiver: any, descriptor: any, result: any) => void; - -export type CurryFunc = T extends (...args: infer Args) => infer R - ? Args extends [infer Arg, ...infer RestArgs] - ? (arg: Arg) => CurryFunc<(...args: RestArgs) => R> - : R - : T; - - export type ToThunkFn = () => ReturnType; export type Thunk = () => ReturnType & { __THUNK__: Symbol }; export type TrlFn = (...args: any[]) => any; -export type TrlAsyncFn = (...args: any[]) => any; - +export type TrlAsyncFn = (...args: any[]) => any; \ No newline at end of file diff --git a/src/utils/utils.ts b/src/utils/utils.ts index a153a8a..5e9445b 100644 --- a/src/utils/utils.ts +++ b/src/utils/utils.ts @@ -1,16 +1,3 @@ -import _ from 'lodash'; -import type {AnyFunction, JSONObject, JSONSerializable} from './types'; - -export function randomText(length: number) { - let result = ''; - const characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'; - const charactersLength = characters.length; - for (let i = 0; i < length; i++) { - result += characters.charAt(Math.floor(Math.random() * charactersLength)); - } - return result; -} - export const uuidV4 = function () { return 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx'.replace(/[x]/g, function (c) { const r = Math.random() * 16 | 0, v = c == 'x' ? r : (r & 0x3 | 0x8); @@ -18,447 +5,6 @@ export const uuidV4 = function () { }); }; -export class IncrementId { - private _id: string; - private readonly _prefix: string; - - constructor(prefix?: string) { - this._prefix = prefix ? prefix : ''; - this._id = this._prefix + '0'; - } - - getId() { - const {_id, _prefix} = this; - if (!_id) { - this._id = _prefix + '0'; - } else { - const idNumStr = _id.substr(_prefix.length, _id.length - _prefix.length); - const newIdNum = parseInt(idNumStr, 10) + 1; - this._id = _prefix + newIdNum.toString(); - } - return this._id; - } -} - -export function incrementId(prefix?: string) { - const _prefix = prefix ? prefix : ''; - let _id = _prefix + '0'; - return function id() { - const idNumStr = _id.substr(_prefix.length, _id.length - _prefix.length); - const newIdNum = parseInt(idNumStr, 10) + 1; - _id = _prefix + newIdNum.toString(); - return _id; - }; -} - -export const getValue = (obj: T, names: K[]): Array => names.map(i => obj[i]); - -export const isObject = (object: string | JSONObject | boolean | AnyFunction | number) => object != null && typeof object === 'object'; - -export const looseEqual = (a: any, b: any): boolean => a == b; - -export const strictEqual = (a: any, b: any): boolean => a === b; - -export const strictObjectIsEqual = (a: any, b: any): boolean => Object.is(a, b); - -export const deepObjectStrictEqual = (object1: JSONSerializable, object2: JSONSerializable) => { - const keys1 = Object.keys(object1); - const keys2 = Object.keys(object2); - if (keys1.length !== keys2.length) { - return false; - } - for (const key of keys1) { - const val1 = object1[key]; - const val2 = object2[key]; - const areObjects = isObject(val1) && isObject(val2); - if ( - areObjects && !deepObjectStrictEqual(val1, val2) || - !areObjects && val1 !== val2 - ) { - return false; - } - } - return true; -}; - -export function reverseColor(oldColor: string) { - const oldColorTemp = '0x' + oldColor.replace(/#/g, ''); - const str = '000000' + (0xFFFFFF - Number(oldColorTemp)).toString(16); - return '#' + str.substring(str.length - 6, str.length); -} - -export const isSameStructure = (objA: unknown, objB: unknown) => { - const objATraversable = objA as JSONSerializable; - const objBTraversable = objB as JSONSerializable; - const objAKeys = Object.keys(objATraversable); - const objBKeys = Object.keys(objBTraversable); - let isSame = true; - if (objAKeys.length !== objBKeys.length) { - return isSame = false; - } else { - objAKeys.forEach((i) => { - if (!objBKeys.includes(i)) { - return isSame = false; - } - }); - return isSame; - } -}; - -export const isLeafParent = (obj: JSONObject) => { - let isLeaf = true; - Object.values(obj).forEach(value => { - if (typeof value === 'object' && value instanceof Array) { - value.forEach(item => { - if (typeof item === 'object') { - return false; - } - }); - return isLeaf = true; - } - if (!['string', 'boolean', 'number', 'undefined', 'function'].includes(typeof value) && (value !== null)) { - return isLeaf = false; - } - }); - return isLeaf; -}; - -export const addDays = (date: Date, days: number): Date => { - date.setDate(date.getDate() + days); - return date; -}; - -export class WaitManager { - private _time30 = 20000; - private readonly _nXSpeed: number = 1; - - constructor(nXSpeed?: number) { - if (nXSpeed === undefined) nXSpeed = 1; - this._nXSpeed = nXSpeed; - } - - private _time1 = 1000; - - get time1(): number { - return this._time1 / this._nXSpeed; - } - - private _time2 = 2000; - - get time2(): number { - return this._time2 / this._nXSpeed; - } - - private _time3 = 3000; - - get time3(): number { - return this._time3 / this._nXSpeed; - } - - private _time4 = 4000; - - get time4(): number { - return this._time4 / this._nXSpeed; - } - - private _time10 = 10000; - - get time10(): number { - return this._time10 / this._nXSpeed; - } - - private _time20 = 20000; - - get time20(): number { - return this._time20 / this._nXSpeed; - } - - get time50(): number { - return this._time30 / this._nXSpeed; - } - - private _time60 = 60000; - - get time60(): number { - return this._time60 / this._nXSpeed; - } - - private _cusTime = 1000; - - get cusTime(): number { - return this._cusTime / this._nXSpeed; - } - - set cusTime(v: number) { - this._cusTime = v; - } -} - -export const wait = async (ms: number, resolveValue?: any) => { - return new Promise((resolve, reject) => { - setTimeout(() => { - const finalResolveValue = resolveValue || true; - resolve(finalResolveValue); - }, ms); - }); -}; - -export function extractValue(data: { key: string, value: Item }[]) { - let result: Item[] = []; - if (data && data.length > 0) { - result = data.map(item => item.value); - } - return result; -} - -export function keyValueToArray(data: { [key: string]: Item }) { - const itemArray: Array = []; - const keys = Object.keys(data); - for (const i of keys) { - itemArray.push({...data[i], _id: i}); - } - return itemArray; -} - -export function minuted(time: number) { - const minutes = Math.floor(time / 60000).toString(); - const seconds = Math.floor((time % 60000) / 1000).toString().padStart(2, '0'); - return `${minutes}:${seconds}`; -} - -export function randomDate(start?: Date, end?: Date, specificProbabilityStart?: Date, specificProbability?: number) { - if (!start) start = new Date('1970-1-1'); - if (!end) end = new Date(); - - if (specificProbabilityStart) { - if (!specificProbability) specificProbability = 0.5; - if (Math.random() <= specificProbability) { - return new Date(specificProbabilityStart.getTime() + Math.random() * (end.getTime() - specificProbabilityStart.getTime())); - } - } - - return new Date(start.getTime() + Math.random() * (end.getTime() - start.getTime())); -} - -export const capitalizeWords = (str: string) => str.replace(/(?:^|\s)\S/g, (a: string) => a.toUpperCase()); - -export const capitalizeFirstLetter = (str: string) => str.charAt(0).toUpperCase() + str.slice(1); - -export const comparerArray = (otherArray: T[], limitKeys?: string[]) => { - return function (current: T) { - return otherArray.filter(function (other: T) { - if (!limitKeys) { - return _.isEqual(current, other); - } else { - // TODO - } - }).length == 0; - }; -}; - -export const onlyInA = (a: T[], b: T[]) => a.filter(comparerArray(b)); - -export const onlyInB = (a: T[], b: T[]) => b.filter(comparerArray(a)); - -export const diffAB = (a: T[], b: T[]) => onlyInA(a, b).concat(onlyInB(a, b)); - -export class StringUtil { - // camelCase - static toCamelCase(str: string) { - return _.camelCase(str); - } - - // snake_case - static toSnakeCase(str: string) { - return _.snakeCase(str); - } - - // PascalCase - static toPascalCase(str: string) { - return _.startCase(_.camelCase(str)).replace(/ /g, ''); - } - - // CONSTANT_CASE - static toConstantCase(str: string) { - return _.upperCase(str).replace(/ /g, '_'); - } - - // kebab-case - static toKebabCase(str: string) { - return _.kebabCase(str); - } - - // lowercase - static toLowerCase(str: string) { - return _.lowerCase(str).replace(/ /g, ''); - } - - // Title Case - static toTitleCase(str: string) { - return _.startCase(_.camelCase(str)); - } - - // Sentence case - static toSentenceCase(str: string) { - return _.upperFirst(_.lowerCase(str)); - } - - // path/case - static toPathCase(str: string) { - return _.lowerCase(str).replace(/ /g, '/'); - } - - // dot.case - static toDotCase(str: string) { - return _.lowerCase(str).replace(/ /g, '.'); - } -} - -export type CaseType = - 'camel' - | 'snake' - | 'pascal' - | 'constant' - | 'kebab' - | 'lower' - | 'title' - | 'sentence' - | 'path' - | 'dot'; -export const deepKeysConvert = (obj: any, toType?: CaseType): any => { - const _toType = toType || 'snake'; - if (Array.isArray(obj)) { - return obj.map(v => deepKeysConvert(v, _toType)); - } else if (obj !== null && obj.constructor === Object) { - return Object.keys(obj).reduce( - (result, key) => { - let newKey = ''; - switch (_toType) { - case 'camel': - newKey = StringUtil.toCamelCase(key); - break; - case 'snake': - newKey = StringUtil.toSnakeCase(key); - break; - case 'pascal': - newKey = StringUtil.toPascalCase(key); - break; - case 'constant': - newKey = StringUtil.toConstantCase(key); - break; - case 'kebab': - newKey = StringUtil.toKebabCase(key); - break; - case 'lower': - newKey = StringUtil.toLowerCase(key); - break; - case 'title': - newKey = StringUtil.toTitleCase(key); - break; - case 'sentence': - newKey = StringUtil.toSentenceCase(key); - break; - case 'path': - newKey = StringUtil.toPathCase(key); - break; - case 'dot': - newKey = StringUtil.toDotCase(key); - break; - default: - newKey = StringUtil.toDotCase(key); - break; - } - return { - ...result, - [newKey]: deepKeysConvert(obj[key], _toType), - }; - }, - {}, - ); - } - return obj; -}; - -export const deepRemoveByKey = (obj: any, keysToBeRemoved: string[]) => { - const result = _.transform(obj, function (result: JSONSerializable, value: any, key: string) { - if (_.isObject(value)) { - value = deepRemoveByKey(value, keysToBeRemoved); - } - if (!keysToBeRemoved.includes(key)) { - _.isArray(obj) ? result.push(value) : result[key] = value; - } - }); - return result as typeof obj; -}; - -export const deepRenameKeys = (obj: JSONSerializable, keysMap: { [key in string]: string }) => { - return _.transform(obj, function (result: JSONSerializable, value: any, key: string | number) { - const currentKey = keysMap[key] || key; - result[currentKey] = _.isObject(value) ? deepRenameKeys(value, keysMap) : value; - }); -}; - -export const deepReplaceValues = (obj: JSONSerializable, keyReducerMap: { [key in string]: (item: JSONSerializable) => any }) => { - const newObject = _.clone(obj) as JSONSerializable; - _.each(obj, (val: any, key: string) => { - for (const item in keyReducerMap) { - if (key === item) { - newObject[key] = keyReducerMap[item](newObject); - } else if (typeof (val) === 'object' || val instanceof Array) { - newObject[key] = deepReplaceValues(val, keyReducerMap); - } - } - }); - return newObject; -}; - -// TODO determine depth and pass root node as a param through callback -export const deepAdd = (obj: JSONSerializable, keyReducerMap: { [key in string]: (item: JSONSerializable) => any }, isItemRootParent?: boolean) => { - const newObject = _.clone(obj) as JSONObject | []; - if (_.isObject(newObject) && !_.isArray(newObject)) { - for (const item in keyReducerMap) { - newObject[item] = keyReducerMap[item](newObject); - } - } - _.each(obj, (val: any, key: string | number) => { - if (_.isObject(val)) { - for (const item in keyReducerMap) { - // @ts-ignore - newObject[key] = deepAdd(val, keyReducerMap, isItemRootParent); - } - } - }); - return newObject; -}; - -const styleString = (color: string) => `color: ${color}; font-weight: bold`; - -const styleHeader = (header: string) => `%c[${header}]`; - -export const bunnyConsole = { - log: (headerLog = 'bunny', ...args: any[]) => { - return console.log(styleHeader(headerLog), styleString('black'), ...args); - }, - warn: (headerLog = 'bunny', ...args: any[]) => { - return console.warn(styleHeader(headerLog), styleString('orange'), ...args); - }, - error: (headerLog = 'bunny', ...args: any[]) => { - return console.error(styleHeader(headerLog), styleString('red'), ...args); - } -}; - -export const timeStart = () => { - return performance ? performance.now() : new Date().getTime(); -}; - -export const timeEnd = (startTime: number, headerLog?: string, consoleConditionFn?: (timeSpent: number) => boolean) => { - const timeSpent = (performance ? performance.now() : new Date().getTime()) - startTime; - const isPassCondition = consoleConditionFn ? consoleConditionFn(timeSpent) : true; - if (isPassCondition) { - bunnyConsole.log(headerLog ? headerLog : 'time spent', timeSpent.toFixed(2)); - } -}; - export const arrayRemove = function (array: T[], predicate: (item: T, index: number, array: T[]) => boolean): T[] { let i = -1, len = array ? array.length : 0; const result = []; @@ -475,35 +21,6 @@ export const arrayRemove = function (array: T[], predicate: (item: T, index: return result; }; -export function memo() { - const cache: { [k: string]: any } = {}; - // eslint-disable-next-line @typescript-eslint/ban-types - return function (target: Object, propertyKey: string, descriptor: PropertyDescriptor) { - const originalMethod = descriptor.value; - descriptor.value = function (...args: any[]) { - const cacheKey = `__cacheKey__${args.toString()}`; - // eslint-disable-next-line no-prototype-builtins - if (!cache.hasOwnProperty(cacheKey)) { - cache[cacheKey] = originalMethod.apply(this, args); - } - return cache[cacheKey]; - } - } -} - -export function zip(array1: T[], array2: T1[], options?: { isToObj: boolean }) { - const zipped: [T, T1][] = []; - const zippedObjCoords: { x: T, y: T1 }[] = []; - const {isToObj} = options ? options : {isToObj: false}; - for (let i = 0; i < array1.length; i++) { - if (isToObj) { - zippedObjCoords.push({x: array1[i], y: array2[i]}) - } else { - zipped.push([array1[i], array2[i]]); - } - } - return isToObj ? zippedObjCoords : zipped; -} /** * data-structure-typed @@ -512,7 +29,7 @@ export function zip(array1: T[], array2: T1[], options? * @copyright Copyright (c) 2022 Tyler Zeng * @license MIT License */ -import {Thunk, ToThunkFn, TrlAsyncFn, TrlFn} from './types'; +import type {Thunk, ToThunkFn, TrlAsyncFn, TrlFn} from './types'; export const THUNK_SYMBOL = Symbol('thunk') diff --git a/tests/unit/data-structures/binary-tree/bst.test.ts b/tests/unit/data-structures/binary-tree/bst.test.ts index b56d3b7..ef3a751 100644 --- a/tests/unit/data-structures/binary-tree/bst.test.ts +++ b/tests/unit/data-structures/binary-tree/bst.test.ts @@ -1,35 +1,40 @@ import {BST, BSTNode} from '../../../../src'; -describe('bst-case6', () => { +describe('BST Case6', () => { it('should perform various operations on a Binary Search Tree', () => { - const arr = [11, 3, 15, 1, 8, 13, 16, 2, 6, 9, 12, 14, 4, 7, 10, 5]; const tree = new BST(); - expect(tree).toBeInstanceOf(BST); - tree.addMany(arr); - + const values = [11, 3, 15, 1, 8, 13, 16, 2, 6, 9, 12, 14, 4, 7, 10, 5]; + tree.addMany(values); expect(tree.root).toBeInstanceOf(BSTNode); + if (tree.root) expect(tree.root.id).toBe(11); + expect(tree.count).toBe(16); + expect(tree.has(6)).toBe(true); const node6 = tree.get(6); expect(node6 && tree.getHeight(node6)).toBe(2); expect(node6 && tree.getDepth(node6)).toBe(3); - const getNodeById = tree.get(10, 'id'); - expect(getNodeById?.id).toBe(10); - const getNodesByCount = tree.getNodes(1, 'count'); - expect(getNodesByCount.length).toBe(16); + const nodeId10 = tree.get(10, 'id'); + expect(nodeId10?.id).toBe(10); - const getMinNodeByRoot = tree.getLeftMost(); - expect(getMinNodeByRoot?.id).toBe(1); + const nodeVal9 = tree.get(9, 'val'); + expect(nodeVal9?.id).toBe(9); + + const nodesByCount1 = tree.getNodes(1, 'count'); + expect(nodesByCount1.length).toBe(16); + + const leftMost = tree.getLeftMost(); + expect(leftMost?.id).toBe(1); const node15 = tree.get(15); - const getMinNodeBySpecificNode = node15 && tree.getLeftMost(node15); - expect(getMinNodeBySpecificNode?.id).toBe(12); + const minNodeBySpecificNode = node15 && tree.getLeftMost(node15); + expect(minNodeBySpecificNode?.id).toBe(12); const subTreeSum = node15 && tree.subTreeSum(node15); expect(subTreeSum).toBe(70); @@ -43,30 +48,33 @@ describe('bst-case6', () => { expect(subTreeAdd).toBeDefined(); } - const node11 = tree.get(11); expect(node11).toBeInstanceOf(BSTNode); if (node11 instanceof BSTNode) { - const allGreaterNodesAdd = tree.allGreaterNodesAdd(node11, 2, 'count'); - expect(allGreaterNodesAdd).toBeDefined(); + const allGreaterNodesAdded = tree.allGreaterNodesAdd(node11, 2, 'count'); + expect(allGreaterNodesAdded).toBeDefined(); } - const dfs = tree.DFS('in', 'node'); - expect(dfs[0].id).toBe(1); - expect(dfs[dfs.length - 1].id).toBe(16); + const dfsInorderNodes = tree.DFS('in', 'node'); + expect(dfsInorderNodes[0].id).toBe(1); + expect(dfsInorderNodes[dfsInorderNodes.length - 1].id).toBe(16); tree.balance(); - const bfs = tree.BFS('node'); expect(tree.isBalanced()).toBe(true); - expect(bfs[0].id).toBe(8); - expect(bfs[bfs.length - 1].id).toBe(16); + + const bfsNodesAfterBalanced = tree.BFS('node'); + expect(bfsNodesAfterBalanced[0].id).toBe(8); + expect(bfsNodesAfterBalanced[bfsNodesAfterBalanced.length - 1].id).toBe(16); const removed11 = tree.remove(11, true); expect(removed11).toBeInstanceOf(Array); expect(removed11[0]).toBeDefined(); expect(removed11[0].deleted).toBeDefined(); + if (removed11[0].deleted) expect(removed11[0].deleted.id).toBe(11); + expect(tree.isAVLBalanced()).toBe(true); + expect(node15 && tree.getHeight(node15)).toBe(2); const removed1 = tree.remove(1, true); @@ -76,6 +84,7 @@ describe('bst-case6', () => { if (removed1[0].deleted) expect(removed1[0].deleted.id).toBe(1); expect(tree.isAVLBalanced()).toBe(true); + expect(tree.getHeight()).toBe(4); const removed4 = tree.remove(4, true); @@ -170,16 +179,16 @@ describe('bst-case6', () => { expect(tree.getHeight()).toBe(2); - expect(!tree.isAVLBalanced()).toBe(true); + expect(tree.isAVLBalanced()).toBe(false); - const lastBFSIds = tree.BFS(); - expect(lastBFSIds[0]).toBe(2); - expect(lastBFSIds[1]).toBe(12); - expect(lastBFSIds[2]).toBe(16); + const bfsIDs = tree.BFS(); + expect(bfsIDs[0]).toBe(2); + expect(bfsIDs[1]).toBe(12); + expect(bfsIDs[2]).toBe(16); - const lastBFSNodes = tree.BFS('node'); - expect(lastBFSNodes[0].id).toBe(2); - expect(lastBFSNodes[1].id).toBe(12); - expect(lastBFSNodes[2].id).toBe(16); + const bfsNodes = tree.BFS('node'); + expect(bfsNodes[0].id).toBe(2); + expect(bfsNodes[1].id).toBe(12); + expect(bfsNodes[2].id).toBe(16); }); }); diff --git a/tests/unit/data-structures/graph/directed-graph.test.ts b/tests/unit/data-structures/graph/directed-graph.test.ts index 5f5ab85..5554814 100644 --- a/tests/unit/data-structures/graph/directed-graph.test.ts +++ b/tests/unit/data-structures/graph/directed-graph.test.ts @@ -1,29 +1,5 @@ import {DirectedEdge, DirectedGraph, DirectedVertex, VertexId} from '../../../../src'; -class MyVertex extends DirectedVertex { - data: string; - - constructor(id: VertexId, data: string) { - super(id); - this.data = data; - } -} - -class MyEdge extends DirectedEdge { - data: string; - - constructor(v1: VertexId, v2: VertexId, weight: number, data: string) { - super(v1, v2, weight); - this.data = data; - } -} - -class MyGraph extends DirectedGraph { - constructor() { - super(); - } -} - describe('DirectedGraph Test1', () => { let graph: DirectedGraph; @@ -69,10 +45,7 @@ describe('DirectedGraph Test1', () => { expect(graph.hasEdge('A', 'B')).toBe(false); }); - // Add more test cases for other methods... - it('should perform topological sort', () => { - // Create a graph with vertices and edges const vertexA = new DirectedVertex('A'); const vertexB = new DirectedVertex('B'); const vertexC = new DirectedVertex('C'); @@ -85,17 +58,43 @@ describe('DirectedGraph Test1', () => { graph.addEdge(edgeAB); graph.addEdge(edgeBC); - // Perform topological sort const topologicalOrder = graph.topologicalSort(); - if (topologicalOrder) expect(topologicalOrder.map(v => v.id)).toEqual(['A', 'B', 'C']); - }); - - // Add more test cases for other methods... }); +class MyVertex extends DirectedVertex { + private _data: string; + get data(): string { + return this._data; + } + set data(value: string) { + this._data = value; + } + + constructor(id: VertexId, data: string) { + super(id); + this._data = data; + } +} + +class MyEdge extends DirectedEdge { + private _data: string; + get data(): string { + return this._data; + } + set data(value: string) { + this._data = value; + } + + constructor(v1: VertexId, v2: VertexId, weight: number, data: string) { + super(v1, v2, weight); + this._data = data; + } +} + + describe('DirectedGraph Test2 operations', () => { const myGraph = new DirectedGraph(); @@ -223,8 +222,6 @@ describe('DirectedGraph Test3', () => { expect(myGraph.getEdge(2, 1)).toBeTruthy(); expect(myGraph.getEdge(1, '100')).toBeFalsy(); - // Add the rest of your assertions here... - myGraph.removeEdgeBetween(1, 2); expect(myGraph.getEdge(1, 2)).toBeFalsy();