-
Notifications
You must be signed in to change notification settings - Fork 17
/
Copy pathutils.js
executable file
·89 lines (81 loc) · 2.04 KB
/
utils.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
export function hex_cp(cp) {
return cp.toString(16).toUpperCase().padStart(2, '0');
}
export function quote_cp(cp) {
return `{${hex_cp(cp)}}`; // raffy convention: like "\u{X}" w/o the "\u"
}
/*
export function explode_cp(s) {
return [...s].map(c => c.codePointAt(0));
}
*/
export function explode_cp(s) { // this is about 2x faster
let cps = [];
for (let pos = 0, len = s.length; pos < len; ) {
let cp = s.codePointAt(pos);
pos += cp < 0x10000 ? 1 : 2;
cps.push(cp);
}
return cps;
}
export function str_from_cps(cps) {
const chunk = 4096;
let len = cps.length;
if (len < chunk) return String.fromCodePoint(...cps);
let buf = [];
for (let i = 0; i < len; ) {
buf.push(String.fromCodePoint(...cps.slice(i, i += chunk)));
}
return buf.join('');
}
export function compare_arrays(a, b) {
let n = a.length;
let c = n - b.length;
for (let i = 0; c == 0 && i < n; i++) c = a[i] - b[i];
return c;
}
export function random_choice(v, rng = Math.random) {
return v[rng() * v.length|0];
}
export function random_sample(v, n, rng = Math.random) {
v = v.slice(); // make copy
if (v.length > n) {
for (let i = 0; i < n; i++) { // shuffle prefix n
let temp = v[i];
let j = Math.floor(i + rng() * (v.length - i));
v[i] = v[j];
v[j] = temp;
}
v = v.slice(0, n); // truncate
}
return v;
}
export function array_replace(v, a, b) {
let prev = 0;
while (true) {
let next = v.indexOf(a, prev);
if (next < 0) break;
v[next] = b;
prev = next + 1;
}
}
export function run_tests(fn, tests) {
let errors = [];
for (let test of tests) {
let {name, norm, error} = test;
if (typeof norm !== 'string') norm = name;
try {
let result = fn(name);
if (error) {
errors.push({type: 'expected error', result, ...test});
} else if (result != norm) {
errors.push({type: 'wrong norm', result, ...test});
}
} catch (err) {
if (!error) {
errors.push({type: 'unexpected error', result: err.message, ...test});
}
}
}
return errors;
}