@softsky/utils 2.3.2 → 2.4.0

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/README.md CHANGED
@@ -61,11 +61,16 @@ ${\textsf{\color{CornflowerBlue}function}}$ combinations - Return all combinatio
61
61
  ${\textsf{\color{CornflowerBlue}function}}$ permutations - Return all permutations of items in array
62
62
 
63
63
  ---
64
- ${\textsf{\color{CornflowerBlue}function}}$ pushToSorted - Push data in array so array is always kept sorted
64
+ ${\textsf{\color{CornflowerBlue}function}}$ pushToSorted - Push data to sorted array. Array will always be kept sorted.
65
65
 
66
- Compare must return true when found position to push in.
67
- For example if we return `[false, false, true, false]`,
68
- Array will become `[false, false, Element, true, false]`.
66
+ Compare function should compare your needed value with value on index passed to it.
67
+ If compare returns 0 it means we found target.
68
+ If compare returns > 0 it means target is smaller.
69
+ If compare returns < 0 it means target is bigger.
70
+
71
+ ```ts
72
+ pushToSorted(numArray, 10, x => x - 10);
73
+ ```
69
74
 
70
75
  ---
71
76
  ${\textsf{\color{CornflowerBlue}function}}$ removeFromArray - Delete value from array.
@@ -210,6 +215,31 @@ pipe(
210
215
  ---
211
216
 
212
217
 
218
+ ## Graphs
219
+ Pos
220
+
221
+ ${\textsf{\color{CornflowerBlue}function}}$ unfoldPathfindingResult - Unfold pathfinding result to path array.
222
+
223
+ ---
224
+ ${\textsf{\color{CornflowerBlue}function}}$ aStar - Pathfind using aStar.
225
+ Returns a target and map of parents.
226
+ You can use `unfoldPathfindingResult()` to get array of nodes.
227
+
228
+ ---
229
+ ${\textsf{\color{CornflowerBlue}function}}$ bfs - Breadth-first search. Slower than dfs.
230
+ If isTarget is omitted becomes floodfill.
231
+ Returns a target and map of parents.
232
+ You can use `unfoldPathfindingResult()` to get array of nodes.
233
+
234
+ ---
235
+ ${\textsf{\color{CornflowerBlue}function}}$ dfs - Depth-first search. Faster than bfs.
236
+ If isTarget is omitted becomes floodfill.
237
+ Returns a target and map of parents.
238
+ You can use `unfoldPathfindingResult()` to get array of nodes.
239
+
240
+ ---
241
+
242
+
213
243
  ## Numbers
214
244
  Numbers, math, etc.
215
245
 
package/dist/arrays.d.ts CHANGED
@@ -14,7 +14,7 @@ export declare function swap<T>(array: T[], index: number, index2: number): T[];
14
14
  * If compare returns > 0 it means we have to cut out bigger side of array.
15
15
  * If compare returns < 0 it means we have to cut out smaller side of array.
16
16
  */
17
- export declare function binarySearch(size: number, compare: (index: number) => number): number;
17
+ export declare function binarySearch(size: number, compare: (index: number) => number, returnClosest?: boolean): number;
18
18
  /** Split array into sub arrays of spicified size */
19
19
  export declare function chunk<T>(array: T[], chunkSize: number): T[][];
20
20
  /** Return all combinations of items in array */
@@ -22,13 +22,18 @@ export declare function combinations<T>(array: T[]): T[][];
22
22
  /** Return all permutations of items in array */
23
23
  export declare function permutations<T>(array: T[]): T[][];
24
24
  /**
25
- * Push data in array so array is always kept sorted
25
+ * Push data to sorted array. Array will always be kept sorted.
26
26
  *
27
- * Compare must return true when found position to push in.
28
- * For example if we return `[false, false, true, false]`,
29
- * Array will become `[false, false, Element, true, false]`.
27
+ * Compare function should compare your needed value with value on index passed to it.
28
+ * If compare returns 0 it means we found target.
29
+ * If compare returns > 0 it means target is smaller.
30
+ * If compare returns < 0 it means target is bigger.
31
+ *
32
+ * ```ts
33
+ * pushToSorted(numArray, 10, x => x - 10);
34
+ * ```
30
35
  */
31
- export declare function pushToSorted<T>(array: T[], element: T, compare: (element: T) => boolean): void;
36
+ export declare function pushToSorted<T>(array: T[], element: T, compare: (x: T) => number): void;
32
37
  /**
33
38
  * Delete value from array.
34
39
  * Only deletes first encountered.
package/dist/arrays.js CHANGED
@@ -32,23 +32,23 @@ export function swap(array, index, index2) {
32
32
  * If compare returns > 0 it means we have to cut out bigger side of array.
33
33
  * If compare returns < 0 it means we have to cut out smaller side of array.
34
34
  */
35
- export function binarySearch(size, compare) {
35
+ export function binarySearch(size, compare, returnClosest) {
36
+ if (size === 0)
37
+ return returnClosest ? 0 : -1;
36
38
  let low = 0;
37
- let high = size - 1;
38
- let position = -1;
39
- while (low <= high) {
40
- const mid = Math.trunc((low + high) / 2);
39
+ let high = size;
40
+ let mid = -1;
41
+ while (high > low) {
42
+ mid = ((low + high) / 2) | 0;
41
43
  const compared = compare(mid);
42
- if (compared === 0) {
43
- position = mid;
44
- break;
45
- }
44
+ if (compared === 0)
45
+ return mid;
46
46
  else if (compared > 0)
47
- high = mid - 1;
47
+ high = mid;
48
48
  else
49
49
  low = mid + 1;
50
50
  }
51
- return position;
51
+ return returnClosest ? mid : -1;
52
52
  }
53
53
  /** Split array into sub arrays of spicified size */
54
54
  export function chunk(array, chunkSize) {
@@ -94,15 +94,20 @@ export function permutations(array) {
94
94
  return result;
95
95
  }
96
96
  /**
97
- * Push data in array so array is always kept sorted
97
+ * Push data to sorted array. Array will always be kept sorted.
98
+ *
99
+ * Compare function should compare your needed value with value on index passed to it.
100
+ * If compare returns 0 it means we found target.
101
+ * If compare returns > 0 it means target is smaller.
102
+ * If compare returns < 0 it means target is bigger.
98
103
  *
99
- * Compare must return true when found position to push in.
100
- * For example if we return `[false, false, true, false]`,
101
- * Array will become `[false, false, Element, true, false]`.
104
+ * ```ts
105
+ * pushToSorted(numArray, 10, x => x - 10);
106
+ * ```
102
107
  */
103
108
  export function pushToSorted(array, element, compare) {
104
- const index = array.findIndex(compare);
105
- array.splice(index === -1 ? array.length : index, 0, element);
109
+ const index = binarySearch(array.length, (x) => compare(array[x]), true);
110
+ array.splice(index, 0, element);
106
111
  }
107
112
  /**
108
113
  * Delete value from array.
@@ -0,0 +1,61 @@
1
+ /**
2
+ * Unfold pathfinding result to path array.
3
+ */
4
+ export declare function unfoldPathfindingResult<T>({ target, parents, }: {
5
+ parents: Map<T, T>;
6
+ target?: T;
7
+ }): T[];
8
+ /**
9
+ * Pathfind using aStar.
10
+ * Returns a target and map of parents.
11
+ * You can use `unfoldPathfindingResult()` to get array of nodes.
12
+ */
13
+ export declare function aStar<T>(options: {
14
+ /** Start node */
15
+ start: T;
16
+ /** Get weight of node */
17
+ getWeight: (node: T) => number;
18
+ /** Presumed cost of going to the target from node */
19
+ heuristic: (node: T) => number;
20
+ /** Get neighbors of node */
21
+ getNeighbors: (node: T) => T[];
22
+ /** Check if node is a target */
23
+ isTarget: (node: T) => boolean;
24
+ }): {
25
+ parents: Map<T, T>;
26
+ target?: T;
27
+ };
28
+ /**
29
+ * Breadth-first search. Slower than dfs.
30
+ * If isTarget is omitted becomes floodfill.
31
+ * Returns a target and map of parents.
32
+ * You can use `unfoldPathfindingResult()` to get array of nodes.
33
+ */
34
+ export declare function bfs<T>(options: {
35
+ /** Start node */
36
+ start: T;
37
+ /** Get neighbors of node */
38
+ getNeighbors: (parent: T) => T[];
39
+ /** Check if node is a target */
40
+ isTarget?: (child: T, parent: T) => boolean;
41
+ }): {
42
+ parents: Map<T, T>;
43
+ target?: T;
44
+ };
45
+ /**
46
+ * Depth-first search. Faster than bfs.
47
+ * If isTarget is omitted becomes floodfill.
48
+ * Returns a target and map of parents.
49
+ * You can use `unfoldPathfindingResult()` to get array of nodes.
50
+ */
51
+ export declare function dfs<T>(options: {
52
+ /** Start node */
53
+ start: T;
54
+ /** Get neighbors of node */
55
+ getNeighbors: (parent: T) => T[];
56
+ /** Check if node is a target */
57
+ isTarget?: (child: T, parent: T) => boolean;
58
+ }): {
59
+ parents: Map<T, T>;
60
+ target?: T;
61
+ };
package/dist/graphs.js ADDED
@@ -0,0 +1,111 @@
1
+ import { pushToSorted } from './arrays';
2
+ /**
3
+ * Unfold pathfinding result to path array.
4
+ */
5
+ export function unfoldPathfindingResult({ target, parents, }) {
6
+ let node = target;
7
+ const path = [];
8
+ while (node) {
9
+ path.push(node);
10
+ node = parents.get(node);
11
+ }
12
+ return path.reverse();
13
+ }
14
+ /**
15
+ * Pathfind using aStar.
16
+ * Returns a target and map of parents.
17
+ * You can use `unfoldPathfindingResult()` to get array of nodes.
18
+ */
19
+ export function aStar(options) {
20
+ const parents = new Map();
21
+ const queue = [
22
+ {
23
+ d: options.start,
24
+ g: 0,
25
+ h: options.heuristic(options.start),
26
+ },
27
+ ];
28
+ while (queue.length > 0) {
29
+ const node = queue.pop();
30
+ if (options.isTarget(node.d))
31
+ return {
32
+ parents,
33
+ target: node.d,
34
+ };
35
+ const neighbors = options.getNeighbors(node.d);
36
+ for (let index = 0; index < neighbors.length; index++) {
37
+ const neighbor = neighbors[index];
38
+ if (options.start === neighbor || parents.has(neighbor))
39
+ continue;
40
+ parents.set(neighbor, node.d);
41
+ const neighborNode = {
42
+ d: neighbor,
43
+ g: node.g + options.getWeight(neighbor),
44
+ h: options.heuristic(neighbor),
45
+ };
46
+ neighborNode.h += node.g;
47
+ pushToSorted(queue, neighborNode, (x) => neighborNode.h - x.h);
48
+ }
49
+ }
50
+ return {
51
+ parents,
52
+ };
53
+ }
54
+ /**
55
+ * Breadth-first search. Slower than dfs.
56
+ * If isTarget is omitted becomes floodfill.
57
+ * Returns a target and map of parents.
58
+ * You can use `unfoldPathfindingResult()` to get array of nodes.
59
+ */
60
+ export function bfs(options) {
61
+ const queue = [options.start];
62
+ const parents = new Map();
63
+ for (let index = 0; index < queue.length; index++) {
64
+ const parent = queue[index];
65
+ const neighbors = options.getNeighbors(parent);
66
+ for (let index = 0; index < neighbors.length; index++) {
67
+ const neighbor = neighbors[index];
68
+ if (neighbor === options.start || parents.has(neighbor))
69
+ continue;
70
+ parents.set(neighbor, parent);
71
+ if (options.isTarget?.(neighbor, parent))
72
+ return {
73
+ target: neighbor,
74
+ parents,
75
+ };
76
+ queue.push(neighbor);
77
+ }
78
+ }
79
+ return {
80
+ parents,
81
+ };
82
+ }
83
+ /**
84
+ * Depth-first search. Faster than bfs.
85
+ * If isTarget is omitted becomes floodfill.
86
+ * Returns a target and map of parents.
87
+ * You can use `unfoldPathfindingResult()` to get array of nodes.
88
+ */
89
+ export function dfs(options) {
90
+ const queue = [options.start];
91
+ const parents = new Map();
92
+ while (queue.length > 0) {
93
+ const node = queue.pop();
94
+ const neighbors = options.getNeighbors(node);
95
+ for (let index = 0; index < neighbors.length; index++) {
96
+ const neighbor = neighbors[index];
97
+ if (neighbor === options.start || parents.has(neighbor))
98
+ continue;
99
+ parents.set(neighbor, node);
100
+ if (options.isTarget?.(neighbor, node))
101
+ return {
102
+ target: neighbor,
103
+ parents,
104
+ };
105
+ queue.push(neighbor);
106
+ }
107
+ }
108
+ return {
109
+ parents,
110
+ };
111
+ }
package/dist/index.d.ts CHANGED
@@ -3,6 +3,7 @@ export * from './consts';
3
3
  export * from './control';
4
4
  export * from './errors';
5
5
  export * from './formatting';
6
+ export * from './graphs';
6
7
  export * from './numbers';
7
8
  export * from './objects';
8
9
  export * from './signals';
package/dist/index.js CHANGED
@@ -3,6 +3,7 @@ export * from './consts';
3
3
  export * from './control';
4
4
  export * from './errors';
5
5
  export * from './formatting';
6
+ export * from './graphs';
6
7
  export * from './numbers';
7
8
  export * from './objects';
8
9
  export * from './signals';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@softsky/utils",
3
- "version": "2.3.2",
3
+ "version": "2.4.0",
4
4
  "description": "JavaScript/TypeScript utilities",
5
5
  "main": "dist/index.js",
6
6
  "scripts": {
@@ -20,8 +20,8 @@
20
20
  },
21
21
  "homepage": "https://github.com/SoundOfTheSky/utils#readme",
22
22
  "devDependencies": {
23
- "@softsky/configs": "^1.3.0",
24
- "@types/bun": "^1.2.8"
23
+ "@softsky/configs": "^1.3.3",
24
+ "@types/bun": "^1.2.11"
25
25
  },
26
26
  "files": ["dist/**/*"]
27
27
  }