data-structure-typed 0.8.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.idea/data-structure-typed.iml +12 -0
- package/.idea/modules.xml +8 -0
- package/.idea/vcs.xml +6 -0
- package/README.md +2 -0
- package/dist/data-structures/binary-tree/aa-tree.js +6 -0
- package/dist/data-structures/binary-tree/avl-tree.js +231 -0
- package/dist/data-structures/binary-tree/b-tree.js +6 -0
- package/dist/data-structures/binary-tree/binary-indexed-tree.js +31 -0
- package/dist/data-structures/binary-tree/binary-tree.js +992 -0
- package/dist/data-structures/binary-tree/bst.js +431 -0
- package/dist/data-structures/binary-tree/index.js +20 -0
- package/dist/data-structures/binary-tree/rb-tree.js +6 -0
- package/dist/data-structures/binary-tree/segment-tree.js +151 -0
- package/dist/data-structures/binary-tree/splay-tree.js +6 -0
- package/dist/data-structures/binary-tree/tree-multiset.js +16 -0
- package/dist/data-structures/binary-tree/two-three-tree.js +6 -0
- package/dist/data-structures/graph/abstract-graph.js +648 -0
- package/dist/data-structures/graph/directed-graph.js +268 -0
- package/dist/data-structures/graph/index.js +19 -0
- package/dist/data-structures/graph/undirected-graph.js +142 -0
- package/dist/data-structures/hash/coordinate-map.js +24 -0
- package/dist/data-structures/hash/coordinate-set.js +21 -0
- package/dist/data-structures/hash/hash-table.js +2 -0
- package/dist/data-structures/hash/index.js +17 -0
- package/dist/data-structures/hash/pair.js +2 -0
- package/dist/data-structures/hash/tree-map.js +2 -0
- package/dist/data-structures/hash/tree-set.js +2 -0
- package/dist/data-structures/heap/heap.js +114 -0
- package/dist/data-structures/heap/index.js +19 -0
- package/dist/data-structures/heap/max-heap.js +22 -0
- package/dist/data-structures/heap/min-heap.js +22 -0
- package/dist/data-structures/index.js +25 -0
- package/dist/data-structures/linked-list/doubly-linked-list.js +259 -0
- package/dist/data-structures/linked-list/index.js +18 -0
- package/dist/data-structures/linked-list/singly-linked-list.js +660 -0
- package/dist/data-structures/linked-list/skip-linked-list.js +2 -0
- package/dist/data-structures/matrix/index.js +19 -0
- package/dist/data-structures/matrix/matrix.js +14 -0
- package/dist/data-structures/matrix/matrix2d.js +119 -0
- package/dist/data-structures/matrix/navigator.js +78 -0
- package/dist/data-structures/matrix/vector2d.js +161 -0
- package/dist/data-structures/priority-queue/index.js +19 -0
- package/dist/data-structures/priority-queue/max-priority-queue.js +15 -0
- package/dist/data-structures/priority-queue/min-priority-queue.js +15 -0
- package/dist/data-structures/priority-queue/priority-queue.js +174 -0
- package/dist/data-structures/queue/deque.js +132 -0
- package/dist/data-structures/queue/index.js +17 -0
- package/dist/data-structures/queue/queue.js +113 -0
- package/dist/data-structures/stack/index.js +17 -0
- package/dist/data-structures/stack/stack.js +97 -0
- package/dist/data-structures/trampoline.js +52 -0
- package/dist/data-structures/trie/index.js +17 -0
- package/dist/data-structures/trie/trie.js +141 -0
- package/dist/index.js +17 -0
- package/dist/types/data-structures/binary-tree/aa-tree.d.ts +2 -0
- package/dist/types/data-structures/binary-tree/avl-tree.d.ts +21 -0
- package/dist/types/data-structures/binary-tree/b-tree.d.ts +2 -0
- package/dist/types/data-structures/binary-tree/binary-indexed-tree.d.ts +8 -0
- package/dist/types/data-structures/binary-tree/binary-tree.d.ts +140 -0
- package/dist/types/data-structures/binary-tree/bst.d.ts +32 -0
- package/dist/types/data-structures/binary-tree/index.d.ts +4 -0
- package/dist/types/data-structures/binary-tree/rb-tree.d.ts +2 -0
- package/dist/types/data-structures/binary-tree/segment-tree.d.ts +33 -0
- package/dist/types/data-structures/binary-tree/splay-tree.d.ts +2 -0
- package/dist/types/data-structures/binary-tree/tree-multiset.d.ts +11 -0
- package/dist/types/data-structures/binary-tree/two-three-tree.d.ts +2 -0
- package/dist/types/data-structures/graph/abstract-graph.d.ts +126 -0
- package/dist/types/data-structures/graph/directed-graph.d.ts +51 -0
- package/dist/types/data-structures/graph/index.d.ts +3 -0
- package/dist/types/data-structures/graph/undirected-graph.d.ts +24 -0
- package/dist/types/data-structures/hash/coordinate-map.d.ts +8 -0
- package/dist/types/data-structures/hash/coordinate-set.d.ts +7 -0
- package/dist/types/data-structures/hash/hash-table.d.ts +1 -0
- package/dist/types/data-structures/hash/index.d.ts +1 -0
- package/dist/types/data-structures/hash/pair.d.ts +1 -0
- package/dist/types/data-structures/hash/tree-map.d.ts +1 -0
- package/dist/types/data-structures/hash/tree-set.d.ts +1 -0
- package/dist/types/data-structures/heap/heap.d.ts +72 -0
- package/dist/types/data-structures/heap/index.d.ts +3 -0
- package/dist/types/data-structures/heap/max-heap.d.ts +14 -0
- package/dist/types/data-structures/heap/min-heap.d.ts +14 -0
- package/dist/types/data-structures/index.d.ts +9 -0
- package/dist/types/data-structures/linked-list/doubly-linked-list.d.ts +59 -0
- package/dist/types/data-structures/linked-list/index.d.ts +2 -0
- package/dist/types/data-structures/linked-list/singly-linked-list.d.ts +358 -0
- package/dist/types/data-structures/linked-list/skip-linked-list.d.ts +1 -0
- package/dist/types/data-structures/matrix/index.d.ts +3 -0
- package/dist/types/data-structures/matrix/matrix.d.ts +9 -0
- package/dist/types/data-structures/matrix/matrix2d.d.ts +25 -0
- package/dist/types/data-structures/matrix/navigator.d.ts +31 -0
- package/dist/types/data-structures/matrix/vector2d.d.ts +74 -0
- package/dist/types/data-structures/priority-queue/index.d.ts +3 -0
- package/dist/types/data-structures/priority-queue/max-priority-queue.d.ts +4 -0
- package/dist/types/data-structures/priority-queue/min-priority-queue.d.ts +4 -0
- package/dist/types/data-structures/priority-queue/priority-queue.d.ts +36 -0
- package/dist/types/data-structures/queue/deque.d.ts +37 -0
- package/dist/types/data-structures/queue/index.d.ts +1 -0
- package/dist/types/data-structures/queue/queue.d.ts +76 -0
- package/dist/types/data-structures/stack/index.d.ts +1 -0
- package/dist/types/data-structures/stack/stack.d.ts +69 -0
- package/dist/types/data-structures/trampoline.d.ts +25 -0
- package/dist/types/data-structures/trie/index.d.ts +1 -0
- package/dist/types/data-structures/trie/trie.d.ts +28 -0
- package/dist/types/index.d.ts +1 -0
- package/dist/types/index.js +17 -0
- package/dist/types/types/index.d.ts +1 -0
- package/dist/types/types/utils.d.ts +46 -0
- package/dist/types/utils.d.ts +122 -0
- package/dist/types/utils.js +53 -0
- package/dist/utils.js +569 -0
- package/package.json +75 -0
- package/src/data-structures/binary-tree/aa-tree.ts +3 -0
- package/src/data-structures/binary-tree/avl-tree.ts +232 -0
- package/src/data-structures/binary-tree/b-tree.ts +3 -0
- package/src/data-structures/binary-tree/binary-indexed-tree.ts +33 -0
- package/src/data-structures/binary-tree/binary-tree.ts +1088 -0
- package/src/data-structures/binary-tree/bst.ts +404 -0
- package/src/data-structures/binary-tree/index.ts +4 -0
- package/src/data-structures/binary-tree/rb-tree.ts +3 -0
- package/src/data-structures/binary-tree/segment-tree.ts +164 -0
- package/src/data-structures/binary-tree/splay-tree.ts +3 -0
- package/src/data-structures/binary-tree/tree-multiset.ts +21 -0
- package/src/data-structures/binary-tree/two-three-tree.ts +3 -0
- package/src/data-structures/graph/abstract-graph.ts +789 -0
- package/src/data-structures/graph/directed-graph.ts +322 -0
- package/src/data-structures/graph/index.ts +3 -0
- package/src/data-structures/graph/undirected-graph.ts +154 -0
- package/src/data-structures/hash/coordinate-map.ts +24 -0
- package/src/data-structures/hash/coordinate-set.ts +20 -0
- package/src/data-structures/hash/hash-table.ts +1 -0
- package/src/data-structures/hash/index.ts +1 -0
- package/src/data-structures/hash/pair.ts +1 -0
- package/src/data-structures/hash/tree-map.ts +1 -0
- package/src/data-structures/hash/tree-set.ts +1 -0
- package/src/data-structures/heap/heap.ts +136 -0
- package/src/data-structures/heap/index.ts +3 -0
- package/src/data-structures/heap/max-heap.ts +22 -0
- package/src/data-structures/heap/min-heap.ts +24 -0
- package/src/data-structures/index.ts +10 -0
- package/src/data-structures/linked-list/doubly-linked-list.ts +258 -0
- package/src/data-structures/linked-list/index.ts +2 -0
- package/src/data-structures/linked-list/singly-linked-list.ts +750 -0
- package/src/data-structures/linked-list/skip-linked-list.ts +1 -0
- package/src/data-structures/matrix/index.ts +3 -0
- package/src/data-structures/matrix/matrix.ts +13 -0
- package/src/data-structures/matrix/matrix2d.ts +125 -0
- package/src/data-structures/matrix/navigator.ts +99 -0
- package/src/data-structures/matrix/vector2d.ts +189 -0
- package/src/data-structures/priority-queue/index.ts +3 -0
- package/src/data-structures/priority-queue/max-priority-queue.ts +12 -0
- package/src/data-structures/priority-queue/min-priority-queue.ts +12 -0
- package/src/data-structures/priority-queue/priority-queue.ts +208 -0
- package/src/data-structures/queue/deque.ts +139 -0
- package/src/data-structures/queue/index.ts +1 -0
- package/src/data-structures/queue/queue.ts +123 -0
- package/src/data-structures/stack/index.ts +1 -0
- package/src/data-structures/stack/stack.ts +104 -0
- package/src/data-structures/trampoline.ts +91 -0
- package/src/data-structures/trie/index.ts +1 -0
- package/src/data-structures/trie/trie.ts +153 -0
- package/src/index.ts +1 -0
- package/src/types/index.ts +1 -0
- package/src/types/patches/index.d.ts +0 -0
- package/src/types/utils.ts +158 -0
- package/src/utils.ts +605 -0
- package/tsconfig.json +52 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
// todo need to be improved
|
|
2
|
+
export class MatrixNTI2D<T = number> {
|
|
3
|
+
private readonly _matrix: Array<Array<T>>;
|
|
4
|
+
|
|
5
|
+
constructor(options: { row: number, col: number, initialVal?: T }) {
|
|
6
|
+
const {row, col, initialVal} = options;
|
|
7
|
+
this._matrix = new Array(row).fill(undefined).map(() => new Array(col).fill(initialVal || 0));
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
toArray(): Array<Array<T>> {
|
|
11
|
+
return this._matrix;
|
|
12
|
+
}
|
|
13
|
+
}
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
import Vector2D from './vector2d'
|
|
2
|
+
|
|
3
|
+
export class Matrix2D {
|
|
4
|
+
private readonly _matrix: number[][];
|
|
5
|
+
|
|
6
|
+
constructor(value?: number[][] | Vector2D) {
|
|
7
|
+
if (typeof value === 'undefined') {
|
|
8
|
+
this._matrix = Matrix2D.identity
|
|
9
|
+
} else if (value instanceof Vector2D) {
|
|
10
|
+
this._matrix = Matrix2D.identity
|
|
11
|
+
this._matrix[0][0] = value.x
|
|
12
|
+
this._matrix[1][0] = value.y
|
|
13
|
+
this._matrix[2][0] = value.w
|
|
14
|
+
} else {
|
|
15
|
+
this._matrix = value
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Return the matrix values
|
|
21
|
+
*/
|
|
22
|
+
public get m(): number[][] {
|
|
23
|
+
return this._matrix
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
public static get empty(): number[][] {
|
|
27
|
+
return [[], [], []]
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
public get toVector(): Vector2D {
|
|
31
|
+
return new Vector2D(this._matrix[0][0], this._matrix[1][0])
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Initialize an identity matrix
|
|
36
|
+
*/
|
|
37
|
+
public static get identity(): number[][] {
|
|
38
|
+
return [
|
|
39
|
+
[1, 0, 0],
|
|
40
|
+
[0, 1, 0],
|
|
41
|
+
[0, 0, 1]]
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
public static add(matrix1: Matrix2D, matrix2: Matrix2D): Matrix2D {
|
|
45
|
+
const result = Matrix2D.empty
|
|
46
|
+
for (let i = 0; i < 3; i++) {
|
|
47
|
+
for (let j = 0; j < 3; j++) {
|
|
48
|
+
result[i][j] = matrix1.m[i][j] + matrix2.m[i][j]
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
return new Matrix2D(result);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
public static subtract(matrix1: Matrix2D, matrix2: Matrix2D): Matrix2D {
|
|
55
|
+
const result = Matrix2D.empty
|
|
56
|
+
for (let i = 0; i < 3; i++) {
|
|
57
|
+
for (let j = 0; j < 3; j++) {
|
|
58
|
+
result[i][j] = matrix1.m[i][j] - matrix2.m[i][j]
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
return new Matrix2D(result);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
public static multiply(matrix1: Matrix2D, matrix2: Matrix2D): Matrix2D {
|
|
65
|
+
const result = Matrix2D.empty
|
|
66
|
+
for (let i = 0; i < 3; i++) {
|
|
67
|
+
for (let j = 0; j < 3; j++) {
|
|
68
|
+
result[i][j] = 0;
|
|
69
|
+
for (let k = 0; k < 3; k++) {
|
|
70
|
+
result[i][j] += matrix1.m[i][k] * matrix2.m[k][j];
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
return new Matrix2D(result);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
public static multiplyByValue(matrix: Matrix2D, value: number): Matrix2D {
|
|
78
|
+
const result = Matrix2D.empty
|
|
79
|
+
for (let i = 0; i < 3; i++) {
|
|
80
|
+
for (let j = 0; j < 3; j++) {
|
|
81
|
+
result[i][j] = matrix.m[i][j] * value
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
return new Matrix2D(result);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
public static multiplyByVector(matrix: Matrix2D, vector: Vector2D): Vector2D {
|
|
88
|
+
return Matrix2D.multiply(matrix, new Matrix2D(vector)).toVector
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
public static view(width: number, height: number): Matrix2D {
|
|
92
|
+
const scaleStep = 1 // Scale every vector * scaleStep
|
|
93
|
+
const centerX = width / 2
|
|
94
|
+
const centerY = height / 2
|
|
95
|
+
const flipX = Math.cos(Math.PI) // rotate 180deg / 3.14radian around X-axis
|
|
96
|
+
|
|
97
|
+
return new Matrix2D([
|
|
98
|
+
[scaleStep, 0, centerX],
|
|
99
|
+
[0, flipX * scaleStep, centerY],
|
|
100
|
+
[0, 0, 1]])
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
public static scale(factor: number) {
|
|
104
|
+
return Matrix2D.multiplyByValue(new Matrix2D(), factor)
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
public static rotate(radians: number) {
|
|
108
|
+
const cos = Math.cos(radians)
|
|
109
|
+
const sin = Math.sin(radians)
|
|
110
|
+
|
|
111
|
+
return new Matrix2D([
|
|
112
|
+
[cos, -sin, 0],
|
|
113
|
+
[sin, cos, 0],
|
|
114
|
+
[0, 0, 1]])
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
public static translate(vector: Vector2D): Matrix2D {
|
|
118
|
+
return new Matrix2D([
|
|
119
|
+
[1, 0, vector.x],
|
|
120
|
+
[0, 1, vector.y],
|
|
121
|
+
[0, 0, vector.w]])
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
export default Matrix2D
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
type Direction = 'up' | 'right' | 'down' | 'left';
|
|
2
|
+
type Turning = { [key in Direction]: Direction };
|
|
3
|
+
|
|
4
|
+
export class Character {
|
|
5
|
+
direction: Direction;
|
|
6
|
+
turn: () => Character;
|
|
7
|
+
|
|
8
|
+
constructor(direction: Direction, turning: Turning) {
|
|
9
|
+
this.direction = direction;
|
|
10
|
+
this.turn = () => new Character(turning[direction], turning);
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
interface NavigatorParams<T> {
|
|
15
|
+
matrix: T[][],
|
|
16
|
+
turning: Turning,
|
|
17
|
+
onMove: (cur: [number, number]) => void
|
|
18
|
+
init: {
|
|
19
|
+
cur: [number, number],
|
|
20
|
+
charDir: Direction,
|
|
21
|
+
VISITED: T,
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export class Navigator<T = number> {
|
|
26
|
+
private readonly _matrix: T[][];
|
|
27
|
+
private readonly _cur: [number, number];
|
|
28
|
+
private _character: Character;
|
|
29
|
+
private readonly _VISITED: T;
|
|
30
|
+
onMove: (cur: [number, number]) => void;
|
|
31
|
+
|
|
32
|
+
constructor({matrix, turning, onMove, init: {cur, charDir, VISITED}}: NavigatorParams<T>) {
|
|
33
|
+
this._matrix = matrix;
|
|
34
|
+
this._cur = cur;
|
|
35
|
+
this._character = new Character(charDir, turning);
|
|
36
|
+
this.onMove = onMove;
|
|
37
|
+
this.onMove && this.onMove(this._cur);
|
|
38
|
+
this._VISITED = VISITED;
|
|
39
|
+
this._matrix[this._cur[0]][this._cur[1]] = this._VISITED;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
start() {
|
|
43
|
+
while (this.check(this._character.direction) || this.check(this._character.turn().direction)) {
|
|
44
|
+
const {direction} = this._character;
|
|
45
|
+
if (this.check(direction)) {
|
|
46
|
+
this.move(direction);
|
|
47
|
+
} else if (this.check(this._character.turn().direction)) {
|
|
48
|
+
this._character = this._character.turn();
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
check(direction: Direction) {
|
|
54
|
+
let forward: T | undefined, row: T[] | undefined;
|
|
55
|
+
const matrix = this._matrix;
|
|
56
|
+
const [i, j] = this._cur;
|
|
57
|
+
switch (direction) {
|
|
58
|
+
case 'up':
|
|
59
|
+
row = matrix[i - 1];
|
|
60
|
+
if (!row) return false;
|
|
61
|
+
forward = row[j];
|
|
62
|
+
break;
|
|
63
|
+
case 'right':
|
|
64
|
+
forward = matrix[i][j + 1];
|
|
65
|
+
break;
|
|
66
|
+
case 'down':
|
|
67
|
+
row = matrix[i + 1];
|
|
68
|
+
if (!row) return false;
|
|
69
|
+
forward = row[j];
|
|
70
|
+
break;
|
|
71
|
+
case 'left':
|
|
72
|
+
forward = matrix[i][j - 1];
|
|
73
|
+
break;
|
|
74
|
+
}
|
|
75
|
+
return forward !== undefined && forward !== this._VISITED;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
move(direction: Direction) {
|
|
79
|
+
switch (direction) {
|
|
80
|
+
case 'up':
|
|
81
|
+
this._cur[0]--;
|
|
82
|
+
break;
|
|
83
|
+
case 'right':
|
|
84
|
+
this._cur[1]++;
|
|
85
|
+
break;
|
|
86
|
+
case 'down':
|
|
87
|
+
this._cur[0]++;
|
|
88
|
+
break;
|
|
89
|
+
case 'left':
|
|
90
|
+
this._cur[1]--;
|
|
91
|
+
break;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
const [i, j] = this._cur;
|
|
95
|
+
this._matrix[i][j] = this._VISITED;
|
|
96
|
+
this.onMove && this.onMove(this._cur);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
|
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
class Vector2D {
|
|
2
|
+
public static add(vector1: Vector2D, vector2: Vector2D): Vector2D {
|
|
3
|
+
return new Vector2D(vector1.x + vector2.x, vector1.y + vector2.y)
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
public static subtract(vector1: Vector2D, vector2: Vector2D): Vector2D {
|
|
7
|
+
return new Vector2D(vector1.x - vector2.x, vector1.y - vector2.y)
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
public static subtractValue(vector: Vector2D, value: number): Vector2D {
|
|
11
|
+
return new Vector2D(vector.x - value, vector.y - value)
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
public static multiply(vector: Vector2D, value: number): Vector2D {
|
|
15
|
+
return new Vector2D(vector.x * value, vector.y * value)
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
public static divide(vector: Vector2D, value: number): Vector2D {
|
|
19
|
+
return new Vector2D(vector.x / value, vector.y / value)
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
public static equals(vector1: Vector2D, vector2: Vector2D): boolean {
|
|
23
|
+
return vector1.x === vector2.x && vector1.y === vector2.y
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
public static equalsRounded(vector1: Vector2D, vector2: Vector2D, roundingFactor = 12): boolean {
|
|
27
|
+
const vector = Vector2D.abs(Vector2D.subtract(vector1, vector2))
|
|
28
|
+
if (vector.x < roundingFactor && vector.y < roundingFactor) {
|
|
29
|
+
return true
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
return false
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Normalizes the vector if it matches a certain condition
|
|
37
|
+
*/
|
|
38
|
+
public static normalize(vector: Vector2D): Vector2D {
|
|
39
|
+
const length = vector.length
|
|
40
|
+
if (length > 2.220446049250313e-16) { // Epsilon
|
|
41
|
+
return Vector2D.divide(vector, length)
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
return vector
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Adjusts x and y so that the length of the vector does not exceed max
|
|
49
|
+
*/
|
|
50
|
+
public static truncate(vector: Vector2D, max: number): Vector2D {
|
|
51
|
+
if (vector.length > max) {
|
|
52
|
+
return Vector2D.multiply(Vector2D.normalize(vector), max)
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
return vector
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* The vector that is perpendicular to this one
|
|
60
|
+
*/
|
|
61
|
+
public static perp(vector: Vector2D): Vector2D {
|
|
62
|
+
return new Vector2D(-vector.y, vector.x)
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* returns the vector that is the reverse of this vector
|
|
67
|
+
*/
|
|
68
|
+
public static reverse(vector: Vector2D): Vector2D {
|
|
69
|
+
return new Vector2D(-vector.x, -vector.y)
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
public static abs(vector: Vector2D): Vector2D {
|
|
73
|
+
return new Vector2D(Math.abs(vector.x), Math.abs(vector.y))
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* The dot product of v1 and v2
|
|
78
|
+
*/
|
|
79
|
+
public static dot(vector1: Vector2D, vector2: Vector2D): number {
|
|
80
|
+
return (vector1.x * vector2.x) + (vector1.y * vector2.y)
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* The distance between this and the vector
|
|
85
|
+
*/
|
|
86
|
+
public static distance(vector1: Vector2D, vector2: Vector2D): number {
|
|
87
|
+
const ySeparation = vector2.y - vector1.y
|
|
88
|
+
const xSeparation = vector2.x - vector1.x
|
|
89
|
+
return Math.sqrt((ySeparation * ySeparation) + (xSeparation * xSeparation))
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* The distance between this and the vector squared
|
|
94
|
+
*/
|
|
95
|
+
public static distanceSq(vector1: Vector2D, vector2: Vector2D): number {
|
|
96
|
+
const ySeparation = vector2.y - vector1.y
|
|
97
|
+
const xSeparation = vector2.x - vector1.x
|
|
98
|
+
return (ySeparation * ySeparation) + (xSeparation * xSeparation)
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* Returns positive if v2 is clockwise of this vector, negative if counterclockwise
|
|
103
|
+
* (assuming the Y axis is pointing down, X axis to right like a Window app)
|
|
104
|
+
*/
|
|
105
|
+
public static sign(vector1: Vector2D, vector2: Vector2D): number {
|
|
106
|
+
if (vector1.y * vector2.x > vector1.x * vector2.y) {
|
|
107
|
+
return -1
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
return 1
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* Returns the angle between origin and the given vector in radians
|
|
115
|
+
* @param vector
|
|
116
|
+
*/
|
|
117
|
+
public static angle(vector: Vector2D): number {
|
|
118
|
+
const origin = new Vector2D(0, -1)
|
|
119
|
+
const radian = Math.acos(Vector2D.dot(vector, origin) / (vector.length * origin.length))
|
|
120
|
+
return Vector2D.sign(vector, origin) === 1 ? ((Math.PI * 2) - radian) : radian
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
public static random(maxX: number, maxY: number): Vector2D {
|
|
124
|
+
const randX = Math.floor(Math.random() * maxX - (maxX / 2))
|
|
125
|
+
const randY = Math.floor(Math.random() * maxY - (maxY / 2))
|
|
126
|
+
return new Vector2D(randX, randY)
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
// /**
|
|
130
|
+
// * Transform vectors based on the current tranformation matrices: translation, rotation and scale
|
|
131
|
+
// * @param vectors The vectors to transform
|
|
132
|
+
// */
|
|
133
|
+
// public static transform(vector: Vector2D, transformation: Matrix2D): Vector2D {
|
|
134
|
+
// return Matrix2D.multiplyByVector(transformation, vector)
|
|
135
|
+
// }
|
|
136
|
+
|
|
137
|
+
// /**
|
|
138
|
+
// * Transform vectors based on the current tranformation matrices: translation, rotation and scale
|
|
139
|
+
// * @param vectors The vectors to transform
|
|
140
|
+
// */
|
|
141
|
+
// public static transformList(vectors: Vector2D[], transformation: Matrix2D): Vector2D[] {
|
|
142
|
+
// return vectors.map(vector => Matrix2D.multiplyByVector(transformation, vector))
|
|
143
|
+
// }
|
|
144
|
+
|
|
145
|
+
constructor(
|
|
146
|
+
public x: number = 0,
|
|
147
|
+
public y: number = 0,
|
|
148
|
+
public w: number = 1 // needed for matrix multiplication
|
|
149
|
+
) {
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
/**
|
|
153
|
+
* Check wether both x and y are zero
|
|
154
|
+
*/
|
|
155
|
+
public zero(): void {
|
|
156
|
+
this.x = 0
|
|
157
|
+
this.y = 0
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
/**
|
|
161
|
+
* Set x and y both to zero
|
|
162
|
+
*/
|
|
163
|
+
public get isZero(): boolean {
|
|
164
|
+
return this.x === 0 && this.y === 0
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
/**
|
|
168
|
+
* The length / magnitude of the vector
|
|
169
|
+
*/
|
|
170
|
+
public get length(): number {
|
|
171
|
+
return Math.sqrt((this.x * this.x) + (this.y * this.y))
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
/**
|
|
175
|
+
* The squared length of the vector
|
|
176
|
+
*/
|
|
177
|
+
public get lengthSq(): number {
|
|
178
|
+
return (this.x * this.x) + (this.y * this.y)
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
/**
|
|
182
|
+
* Return the vector with rounded values
|
|
183
|
+
*/
|
|
184
|
+
public get rounded(): Vector2D {
|
|
185
|
+
return new Vector2D(Math.round(this.x), Math.round(this.y))
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
export default Vector2D
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import {PriorityQueue, PriorityQueueOptions} from './priority-queue';
|
|
2
|
+
|
|
3
|
+
export class MaxPriorityQueue<T = number> extends PriorityQueue<T> {
|
|
4
|
+
constructor(options: PriorityQueueOptions<T>) {
|
|
5
|
+
super({
|
|
6
|
+
nodes: options.nodes, comparator: (a: T, b: T) => {
|
|
7
|
+
const aKey = a as unknown as number, bKey = b as unknown as number;
|
|
8
|
+
return bKey - aKey;
|
|
9
|
+
}
|
|
10
|
+
});
|
|
11
|
+
}
|
|
12
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import {PriorityQueue, PriorityQueueOptions} from './priority-queue';
|
|
2
|
+
|
|
3
|
+
export class MinPriorityQueue<T = number> extends PriorityQueue<T> {
|
|
4
|
+
constructor(options: PriorityQueueOptions<T>) {
|
|
5
|
+
super({
|
|
6
|
+
nodes: options.nodes, comparator: (a: T, b: T) => {
|
|
7
|
+
const aKey = a as unknown as number, bKey = b as unknown as number;
|
|
8
|
+
return aKey - bKey;
|
|
9
|
+
}
|
|
10
|
+
});
|
|
11
|
+
}
|
|
12
|
+
}
|
|
@@ -0,0 +1,208 @@
|
|
|
1
|
+
export type PriorityQueueComparator<T> = (a: T, b: T) => number;
|
|
2
|
+
|
|
3
|
+
export interface PriorityQueueOptions<T> {
|
|
4
|
+
nodes?: T[];
|
|
5
|
+
isFix?: boolean;
|
|
6
|
+
comparator: PriorityQueueComparator<T>;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export type PriorityQueueDFSOrderPattern = 'pre' | 'in' | 'post';
|
|
10
|
+
|
|
11
|
+
export class PriorityQueue<T = number> {
|
|
12
|
+
protected nodes: T[] = [];
|
|
13
|
+
|
|
14
|
+
get size(): number {
|
|
15
|
+
return this.nodes.length;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
protected readonly _comparator: PriorityQueueComparator<T> = (a: T, b: T) => {
|
|
19
|
+
const aKey = a as unknown as number, bKey = b as unknown as number;
|
|
20
|
+
return aKey - bKey;
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
constructor(options: PriorityQueueOptions<T>) {
|
|
24
|
+
const {nodes, comparator, isFix = true} = options;
|
|
25
|
+
this._comparator = comparator;
|
|
26
|
+
|
|
27
|
+
if (nodes && nodes instanceof Array && nodes.length > 0) {
|
|
28
|
+
// TODO support distinct
|
|
29
|
+
this.nodes = Array.isArray(nodes) ? [...nodes] : [];
|
|
30
|
+
isFix && this._fix();
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
protected _compare(a: number, b: number) {
|
|
35
|
+
return this._comparator(this.nodes[a], this.nodes[b]) > 0;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
protected _swap(a: number, b: number) {
|
|
39
|
+
const temp = this.nodes[a];
|
|
40
|
+
this.nodes[a] = this.nodes[b];
|
|
41
|
+
this.nodes[b] = temp;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
protected _isValidIndex(index: number): boolean {
|
|
45
|
+
return index > -1 && index < this.nodes.length;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
protected _getParent(child: number): number {
|
|
49
|
+
return Math.floor((child - 1) / 2);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
protected _getLeft(parent: number): number {
|
|
53
|
+
return (2 * parent) + 1;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
protected _getRight(parent: number): number {
|
|
57
|
+
return (2 * parent) + 2;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
protected _getComparedChild(parent: number) {
|
|
61
|
+
let min = parent;
|
|
62
|
+
const left = this._getLeft(parent), right = this._getRight(parent);
|
|
63
|
+
|
|
64
|
+
if (left < this.size && this._compare(min, left)) {
|
|
65
|
+
min = left;
|
|
66
|
+
}
|
|
67
|
+
if (right < this.size && this._compare(min, right)) {
|
|
68
|
+
min = right;
|
|
69
|
+
}
|
|
70
|
+
return min;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
protected _heapifyUp(start: number) {
|
|
74
|
+
while (start > 0 && this._compare(this._getParent(start), start)) {
|
|
75
|
+
const parent = this._getParent(start);
|
|
76
|
+
this._swap(start, parent);
|
|
77
|
+
start = parent;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
protected _heapifyDown(start: number) {
|
|
82
|
+
let min = this._getComparedChild(start);
|
|
83
|
+
while (this._compare(start, min)) {
|
|
84
|
+
this._swap(min, start);
|
|
85
|
+
start = min;
|
|
86
|
+
min = this._getComparedChild(start);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
protected _fix() {
|
|
91
|
+
for (let i = Math.floor(this.size / 2); i > -1; i--) this._heapifyDown(i);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
offer(node: T) {
|
|
95
|
+
this.nodes.push(node);
|
|
96
|
+
this._heapifyUp(this.size - 1);
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
peek(): T | null {
|
|
100
|
+
return this.size ? this.nodes[0] : null;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
poll(): T | null {
|
|
104
|
+
let res: T | null = null;
|
|
105
|
+
if (this.size > 1) {
|
|
106
|
+
this._swap(0, this.nodes.length - 1);
|
|
107
|
+
res = this.nodes.pop() ?? null;
|
|
108
|
+
this._heapifyDown(0);
|
|
109
|
+
} else if (this.size === 1) {
|
|
110
|
+
res = this.nodes.pop() ?? null;
|
|
111
|
+
}
|
|
112
|
+
return res;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
leaf(): T | null {
|
|
116
|
+
return this.nodes[this.size - 1] ?? null;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
isEmpty() {
|
|
120
|
+
return this.size === 0;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
clear() {
|
|
124
|
+
this.nodes = [];
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
toArray(): T[] {
|
|
128
|
+
return [...this.nodes];
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
clone(): PriorityQueue<T> {
|
|
132
|
+
return new PriorityQueue<T>({nodes: this.nodes, comparator: this._comparator});
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
// --- start additional methods ---
|
|
136
|
+
isValid(): boolean {
|
|
137
|
+
const isValidRecursive = (parentIndex: number): boolean => {
|
|
138
|
+
let isValidLeft = true;
|
|
139
|
+
let isValidRight = true;
|
|
140
|
+
|
|
141
|
+
if (this._getLeft(parentIndex) !== -1) {
|
|
142
|
+
const leftChildIndex = (parentIndex * 2) + 1;
|
|
143
|
+
if (!this._compare(parentIndex, leftChildIndex)) return false;
|
|
144
|
+
isValidLeft = isValidRecursive(leftChildIndex);
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
if (this._getRight(parentIndex) !== -1) {
|
|
148
|
+
const rightChildIndex = (parentIndex * 2) + 2;
|
|
149
|
+
if (!this._compare(parentIndex, rightChildIndex)) return false;
|
|
150
|
+
isValidRight = isValidRecursive(rightChildIndex);
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
return isValidLeft && isValidRight;
|
|
154
|
+
};
|
|
155
|
+
|
|
156
|
+
return isValidRecursive(0);
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
sort(): T[] {
|
|
160
|
+
const visitedNode: T[] = [];
|
|
161
|
+
while (this.size !== 0) {
|
|
162
|
+
const top = this.poll();
|
|
163
|
+
if (top) visitedNode.push(top);
|
|
164
|
+
}
|
|
165
|
+
return visitedNode;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
DFS(dfsMode: PriorityQueueDFSOrderPattern): (T | null)[] {
|
|
169
|
+
const visitedNode: (T | null)[] = [];
|
|
170
|
+
|
|
171
|
+
const traverse = (cur: number) => {
|
|
172
|
+
const leftChildIndex = this._getLeft(cur);
|
|
173
|
+
const rightChildIndex = this._getRight(cur);
|
|
174
|
+
switch (dfsMode) {
|
|
175
|
+
case 'in':
|
|
176
|
+
this._isValidIndex(leftChildIndex) && traverse(leftChildIndex);
|
|
177
|
+
visitedNode.push(this.nodes[cur] ?? null);
|
|
178
|
+
this._isValidIndex(rightChildIndex) && traverse(rightChildIndex);
|
|
179
|
+
break;
|
|
180
|
+
case 'pre':
|
|
181
|
+
visitedNode.push(this.nodes[cur] ?? null);
|
|
182
|
+
this._isValidIndex(leftChildIndex) && traverse(leftChildIndex);
|
|
183
|
+
this._isValidIndex(rightChildIndex) && traverse(rightChildIndex);
|
|
184
|
+
break;
|
|
185
|
+
case 'post':
|
|
186
|
+
this._isValidIndex(leftChildIndex) && traverse(leftChildIndex);
|
|
187
|
+
this._isValidIndex(rightChildIndex) && traverse(rightChildIndex);
|
|
188
|
+
visitedNode.push(this.nodes[cur] ?? null);
|
|
189
|
+
break;
|
|
190
|
+
}
|
|
191
|
+
};
|
|
192
|
+
|
|
193
|
+
this._isValidIndex(0) && traverse(0);
|
|
194
|
+
return visitedNode;
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
static heapify<T>(options: PriorityQueueOptions<T>) {
|
|
198
|
+
const heap = new PriorityQueue(options);
|
|
199
|
+
heap._fix();
|
|
200
|
+
return heap;
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
static isPriorityQueueified<T>(options: Omit<PriorityQueueOptions<T>, 'isFix'>) {
|
|
204
|
+
return new PriorityQueue({...options, isFix: true}).isValid();
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
// --- end additional methods ---
|
|
208
|
+
}
|