@softsky/utils 2.6.0 → 2.7.1
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 +27 -3
- package/dist/arrays.d.ts +2 -0
- package/dist/arrays.js +11 -0
- package/dist/graphs.d.ts +18 -0
- package/dist/graphs.js +146 -0
- package/dist/time.d.ts +10 -3
- package/dist/time.js +11 -3
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -84,6 +84,9 @@ Only deletes last encountered.
|
|
|
84
84
|
|
|
85
85
|
Returns index of deleted value.
|
|
86
86
|
|
|
87
|
+
---
|
|
88
|
+
__function__ `reverse` - Reverse part of array
|
|
89
|
+
|
|
87
90
|
---
|
|
88
91
|
|
|
89
92
|
|
|
@@ -291,6 +294,21 @@ If isTarget is omitted becomes floodfill.
|
|
|
291
294
|
Returns a target and map of parents.
|
|
292
295
|
You can use `unfoldPathfindingResult()` to get array of nodes.
|
|
293
296
|
|
|
297
|
+
---
|
|
298
|
+
__function__ `knapsack` - Knapsack find best way to get maximum value in limited capacity
|
|
299
|
+
|
|
300
|
+
---
|
|
301
|
+
__function__ `hamiltonianCycle` - Find min path between points. You need to supply 2-dim array
|
|
302
|
+
where first index is a point and second index is a distance from this point to another.
|
|
303
|
+
Put infinity if where are no path. Returns cycle (start and end at the same point)
|
|
304
|
+
Original: https://github.com/qntm/held-karp
|
|
305
|
+
|
|
306
|
+
---
|
|
307
|
+
__function__ `traverseByNearestNeighbor` - Traverse all points by nearest neighbor. Should be able to go from any point to any other point.
|
|
308
|
+
|
|
309
|
+
---
|
|
310
|
+
__function__ `twoOpt` - 2-opt improvement
|
|
311
|
+
|
|
294
312
|
---
|
|
295
313
|
|
|
296
314
|
|
|
@@ -505,14 +523,20 @@ Returns clear function.
|
|
|
505
523
|
For cron string syntax check __getNextCron()__ description
|
|
506
524
|
|
|
507
525
|
---
|
|
508
|
-
__function__ `getNextCron` - Find next cron date after passed date.
|
|
526
|
+
__function__ `getNextCron` - Find next cron date after passed date. This function __DOES NOT__ implement regular CRON 1 to 1.
|
|
509
527
|
|
|
510
|
-
|
|
528
|
+
1. [0-999] Milliseconds
|
|
529
|
+
2. [0-59] Seconds
|
|
530
|
+
3. [0-59] Minutes
|
|
531
|
+
4. [0-23] Hours
|
|
532
|
+
5. [1-31] Dates
|
|
533
|
+
6. [1-12] Months
|
|
534
|
+
7. [0-6] Weekdays
|
|
511
535
|
|
|
512
536
|
Main differences:
|
|
513
537
|
- Weekdays value only 0 to 6 (0 is Sunday)
|
|
514
538
|
- New supported syntax: __30-60/10__ - means __30,40,50,60__
|
|
515
|
-
- Second and millisecond support:
|
|
539
|
+
- Second and millisecond support: __0,500 300__ - every 30 seconds, two times
|
|
516
540
|
|
|
517
541
|
---
|
|
518
542
|
__class__ `SpeedCalculator` - Object that calculates speed, ETA and percent of any measurable task.
|
package/dist/arrays.d.ts
CHANGED
|
@@ -48,3 +48,5 @@ export declare function removeFromArray<T>(array: T[], value: T): number;
|
|
|
48
48
|
* Returns index of deleted value.
|
|
49
49
|
*/
|
|
50
50
|
export declare function removeLastFromArray<T>(array: T[], value: T): number;
|
|
51
|
+
/** Reverse part of array */
|
|
52
|
+
export declare function reverse<T>(array: T[], start: number, end: number): T[];
|
package/dist/arrays.js
CHANGED
|
@@ -133,3 +133,14 @@ export function removeLastFromArray(array, value) {
|
|
|
133
133
|
array.splice(index, 1);
|
|
134
134
|
return index;
|
|
135
135
|
}
|
|
136
|
+
/** Reverse part of array */
|
|
137
|
+
export function reverse(array, start, end) {
|
|
138
|
+
array = [...array];
|
|
139
|
+
const n = ((end - start + 1) / 2) | 0;
|
|
140
|
+
for (let index = 0; index < n; index++) {
|
|
141
|
+
const temporary = array[start + index];
|
|
142
|
+
array[start + index] = array[end - index];
|
|
143
|
+
array[end - index] = temporary;
|
|
144
|
+
}
|
|
145
|
+
return array;
|
|
146
|
+
}
|
package/dist/graphs.d.ts
CHANGED
|
@@ -59,3 +59,21 @@ export declare function dfs<T>(options: {
|
|
|
59
59
|
parents: Map<T, T>;
|
|
60
60
|
target?: T;
|
|
61
61
|
};
|
|
62
|
+
/** Knapsack find best way to get maximum value in limited capacity */
|
|
63
|
+
export declare function knapsack(weights: number[], values: number[], capacity: number): {
|
|
64
|
+
weight: number;
|
|
65
|
+
items: number[];
|
|
66
|
+
};
|
|
67
|
+
/**
|
|
68
|
+
* Find min path between points. You need to supply 2-dim array
|
|
69
|
+
* where first index is a point and second index is a distance from this point to another.
|
|
70
|
+
* Put infinity if where are no path. Returns cycle (start and end at the same point)
|
|
71
|
+
* Original: https://github.com/qntm/held-karp
|
|
72
|
+
*/
|
|
73
|
+
export declare function hamiltonianCycle(distribution: number[][]): number[];
|
|
74
|
+
/**
|
|
75
|
+
* Traverse all points by nearest neighbor. Should be able to go from any point to any other point.
|
|
76
|
+
*/
|
|
77
|
+
export declare function traverseByNearestNeighbor(distribution: number[][]): number[];
|
|
78
|
+
/** 2-opt improvement */
|
|
79
|
+
export declare function twoOpt(tour: number[], distribution: number[][]): number[];
|
package/dist/graphs.js
CHANGED
|
@@ -109,3 +109,149 @@ export function dfs(options) {
|
|
|
109
109
|
parents,
|
|
110
110
|
};
|
|
111
111
|
}
|
|
112
|
+
/** Knapsack find best way to get maximum value in limited capacity */
|
|
113
|
+
export function knapsack(weights, values, capacity) {
|
|
114
|
+
const n = weights.length;
|
|
115
|
+
const dp = Array.from({ length: n + 1 }, () => new Array(capacity + 1).fill(0));
|
|
116
|
+
for (let index = 1; index <= n; index++) {
|
|
117
|
+
const w = weights[index - 1];
|
|
118
|
+
const v = values[index - 1];
|
|
119
|
+
const dpc = dp[index];
|
|
120
|
+
const dpl = dp[index - 1];
|
|
121
|
+
for (let c = 0; c <= capacity; c++)
|
|
122
|
+
dpc[c] = w > c ? dpl[c] : Math.max(dpl[c], dpl[c - w] + v);
|
|
123
|
+
}
|
|
124
|
+
const items = [];
|
|
125
|
+
let c = capacity;
|
|
126
|
+
for (let index = n; index > 0 && c > 0; index--) {
|
|
127
|
+
if (dp[index][c] !== dp[index - 1][c]) {
|
|
128
|
+
items.push(index - 1);
|
|
129
|
+
c -= weights[index - 1];
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
return { weight: dp[n][capacity], items: items.reverse() };
|
|
133
|
+
}
|
|
134
|
+
/**
|
|
135
|
+
* Find min path between points. You need to supply 2-dim array
|
|
136
|
+
* where first index is a point and second index is a distance from this point to another.
|
|
137
|
+
* Put infinity if where are no path. Returns cycle (start and end at the same point)
|
|
138
|
+
* Original: https://github.com/qntm/held-karp
|
|
139
|
+
*/
|
|
140
|
+
export function hamiltonianCycle(distribution) {
|
|
141
|
+
const n = distribution.length;
|
|
142
|
+
if (n === 1)
|
|
143
|
+
return [0, 0];
|
|
144
|
+
const all = (1 << (n - 1)) - 1;
|
|
145
|
+
const length = new Float64Array((1 << (n - 1)) * (n - 1));
|
|
146
|
+
const previous = new Uint8Array((1 << (n - 1)) * (n - 1));
|
|
147
|
+
let S = 0;
|
|
148
|
+
do {
|
|
149
|
+
S++;
|
|
150
|
+
let v = n - 1;
|
|
151
|
+
do {
|
|
152
|
+
v--;
|
|
153
|
+
const S2 = S ^ (1 << v);
|
|
154
|
+
if (S2 < S) {
|
|
155
|
+
let bestL = 0;
|
|
156
|
+
let bestU = 0;
|
|
157
|
+
if (S2) {
|
|
158
|
+
bestL = Infinity;
|
|
159
|
+
let u = n - 1;
|
|
160
|
+
do {
|
|
161
|
+
u--;
|
|
162
|
+
if (S2 & (1 << u)) {
|
|
163
|
+
const l = length[(n - 1) * S2 + u] + distribution[u][v];
|
|
164
|
+
if (l <= bestL) {
|
|
165
|
+
bestL = l;
|
|
166
|
+
bestU = u;
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
} while (u);
|
|
170
|
+
}
|
|
171
|
+
else {
|
|
172
|
+
bestL = distribution[n - 1][v];
|
|
173
|
+
bestU = n - 1;
|
|
174
|
+
}
|
|
175
|
+
length[(n - 1) * S + v] = bestL;
|
|
176
|
+
previous[(n - 1) * S + v] = bestU;
|
|
177
|
+
}
|
|
178
|
+
} while (v);
|
|
179
|
+
} while (S < all);
|
|
180
|
+
let bestL = Infinity;
|
|
181
|
+
let bestU = -1;
|
|
182
|
+
let u = n - 1;
|
|
183
|
+
do {
|
|
184
|
+
u--;
|
|
185
|
+
const l = length[(n - 1) * all + u] + distribution[u][n - 1];
|
|
186
|
+
if (l <= bestL) {
|
|
187
|
+
bestL = l;
|
|
188
|
+
bestU = u;
|
|
189
|
+
}
|
|
190
|
+
} while (u);
|
|
191
|
+
const cycle = [n - 1];
|
|
192
|
+
u = bestU;
|
|
193
|
+
S = all;
|
|
194
|
+
while (u !== n - 1) {
|
|
195
|
+
cycle.unshift(u);
|
|
196
|
+
const S2 = S ^ (1 << u);
|
|
197
|
+
u = previous[(n - 1) * S + u];
|
|
198
|
+
S = S2;
|
|
199
|
+
}
|
|
200
|
+
const index = cycle.indexOf(0);
|
|
201
|
+
return [...cycle.slice(index), ...cycle.slice(0, index), 0];
|
|
202
|
+
}
|
|
203
|
+
/**
|
|
204
|
+
* Traverse all points by nearest neighbor. Should be able to go from any point to any other point.
|
|
205
|
+
*/
|
|
206
|
+
export function traverseByNearestNeighbor(distribution) {
|
|
207
|
+
const n = distribution.length;
|
|
208
|
+
const toVisit = new Array(n).fill(true);
|
|
209
|
+
const path = [0];
|
|
210
|
+
let last = 0;
|
|
211
|
+
toVisit[0] = false;
|
|
212
|
+
for (let index = 1; index < n; index++) {
|
|
213
|
+
let nearest = -1;
|
|
214
|
+
let nearestDistribution = Infinity;
|
|
215
|
+
for (let index = 0; index < n; index++) {
|
|
216
|
+
if (toVisit[index] && distribution[last][index] < nearestDistribution) {
|
|
217
|
+
nearest = index;
|
|
218
|
+
nearestDistribution = distribution[last][index];
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
path.push(nearest);
|
|
222
|
+
last = nearest;
|
|
223
|
+
toVisit[nearest] = false;
|
|
224
|
+
}
|
|
225
|
+
return path;
|
|
226
|
+
}
|
|
227
|
+
/** 2-opt improvement */
|
|
228
|
+
export function twoOpt(tour, distribution) {
|
|
229
|
+
let improved = true;
|
|
230
|
+
const nStart = tour.length - 2;
|
|
231
|
+
const nEnd = tour.length - 1;
|
|
232
|
+
while (improved) {
|
|
233
|
+
improved = false;
|
|
234
|
+
for (let start = 1; start < nStart; start++) {
|
|
235
|
+
for (let end = start + 1; end < nEnd; end++) {
|
|
236
|
+
const t0 = distribution[tour[start - 1]];
|
|
237
|
+
const t1 = tour[start];
|
|
238
|
+
const tk1 = tour[end];
|
|
239
|
+
const tk2 = tour[end + 1];
|
|
240
|
+
if (t0[tk1] +
|
|
241
|
+
distribution[t1][tk2] -
|
|
242
|
+
t0[t1] -
|
|
243
|
+
distribution[tk1][tk2] <
|
|
244
|
+
-1e-9) {
|
|
245
|
+
const n = ((end - start + 1) / 2) | 0;
|
|
246
|
+
for (let index = 0; index < n; index++) {
|
|
247
|
+
const temporary = tour[start + index];
|
|
248
|
+
tour[start + index] = tour[end - index];
|
|
249
|
+
tour[end - index] = temporary;
|
|
250
|
+
}
|
|
251
|
+
improved = true;
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
return tour;
|
|
257
|
+
}
|
package/dist/time.d.ts
CHANGED
|
@@ -22,14 +22,21 @@ export declare function setSafeInterval(handler: AnyFunction, delay: number): ()
|
|
|
22
22
|
* Returns clear function.
|
|
23
23
|
* For cron string syntax check __getNextCron()__ description */
|
|
24
24
|
export declare function cronInterval(run: () => unknown, cronString: string): () => void;
|
|
25
|
-
/** Find next cron date after passed date.
|
|
25
|
+
/** Find next cron date after passed date. This function __DOES NOT__ implement regular CRON 1 to 1.
|
|
26
26
|
*
|
|
27
|
-
*
|
|
27
|
+
* 1. [0-999] Milliseconds
|
|
28
|
+
* 2. [0-59] Seconds
|
|
29
|
+
* 3. [0-59] Minutes
|
|
30
|
+
* 4. [0-23] Hours
|
|
31
|
+
* 5. [1-31] Dates
|
|
32
|
+
* 6. [1-12] Months
|
|
33
|
+
* 7. [0-6] Weekdays
|
|
28
34
|
*
|
|
29
35
|
* Main differences:
|
|
30
36
|
* - Weekdays value only 0 to 6 (0 is Sunday)
|
|
31
37
|
* - New supported syntax: __30-60/10__ - means __30,40,50,60__
|
|
32
|
-
* - Second and millisecond support:
|
|
38
|
+
* - Second and millisecond support: __0,500 300__ - every 30 seconds, two times
|
|
39
|
+
* */
|
|
33
40
|
export declare function getNextCron(cronString: string, datetime?: Date): Date;
|
|
34
41
|
/**
|
|
35
42
|
* Object that calculates speed, ETA and percent of any measurable task.
|
package/dist/time.js
CHANGED
|
@@ -79,14 +79,21 @@ export function cronInterval(run, cronString) {
|
|
|
79
79
|
clearTimeout(timeout);
|
|
80
80
|
};
|
|
81
81
|
}
|
|
82
|
-
/** Find next cron date after passed date.
|
|
82
|
+
/** Find next cron date after passed date. This function __DOES NOT__ implement regular CRON 1 to 1.
|
|
83
83
|
*
|
|
84
|
-
*
|
|
84
|
+
* 1. [0-999] Milliseconds
|
|
85
|
+
* 2. [0-59] Seconds
|
|
86
|
+
* 3. [0-59] Minutes
|
|
87
|
+
* 4. [0-23] Hours
|
|
88
|
+
* 5. [1-31] Dates
|
|
89
|
+
* 6. [1-12] Months
|
|
90
|
+
* 7. [0-6] Weekdays
|
|
85
91
|
*
|
|
86
92
|
* Main differences:
|
|
87
93
|
* - Weekdays value only 0 to 6 (0 is Sunday)
|
|
88
94
|
* - New supported syntax: __30-60/10__ - means __30,40,50,60__
|
|
89
|
-
* - Second and millisecond support:
|
|
95
|
+
* - Second and millisecond support: __0,500 300__ - every 30 seconds, two times
|
|
96
|
+
* */
|
|
90
97
|
export function getNextCron(cronString, datetime = new Date()) {
|
|
91
98
|
const cron = cronString.split(' ');
|
|
92
99
|
for (let index = cron.length; index < 7; index++)
|
|
@@ -244,6 +251,7 @@ export class SpeedCalculator {
|
|
|
244
251
|
: {
|
|
245
252
|
speed,
|
|
246
253
|
percent: this.sum / this.size,
|
|
254
|
+
// eslint-disable-next-line @typescript-eslint/no-unnecessary-type-conversion
|
|
247
255
|
eta: ~~((this.size - this.sum) / speed) * 1000,
|
|
248
256
|
};
|
|
249
257
|
}
|