@calcit/ternary-tree 0.0.16 → 0.0.19-a1
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/lib/{hash.d.ts → hash.d.mts} +0 -0
- package/lib/{hash.js → hash.mjs} +0 -0
- package/lib/index.d.mts +4 -0
- package/lib/index.mjs +4 -0
- package/lib/{list.d.ts → list.d.mts} +2 -1
- package/lib/{list.js → list.mjs} +12 -4
- package/lib/main.d.mts +2 -0
- package/lib/{main.js → main.mjs} +6 -6
- package/lib/{map.d.ts → map.d.mts} +3 -2
- package/lib/{map.js → map.mjs} +62 -29
- package/lib/{test-list.d.ts → test-list.d.mts} +0 -0
- package/lib/{test-list.js → test-list.mjs} +24 -3
- package/lib/{test-map.d.ts → test-map.d.mts} +0 -0
- package/lib/{test-map.js → test-map.mjs} +18 -18
- package/lib/{types.d.ts → types.d.mts} +0 -0
- package/lib/{types.js → types.mjs} +0 -0
- package/lib/{utils.d.ts → utils.d.mts} +2 -2
- package/lib/{utils.js → utils.mjs} +3 -3
- package/package.json +9 -7
- package/assets/index.html +0 -2
- package/lib/bundle.js +0 -2979
- package/lib/bundle.js.map +0 -1
- package/lib/index.d.ts +0 -4
- package/lib/index.js +0 -4
- package/lib/main.d.ts +0 -2
- package/src/costs.nim +0 -62
- package/src/hash.ts +0 -78
- package/src/index.ts +0 -5
- package/src/list.ts +0 -987
- package/src/main.ts +0 -20
- package/src/map.ts +0 -1307
- package/src/shape.nim +0 -62
- package/src/test-list.ts +0 -264
- package/src/test-map.ts +0 -287
- package/src/types.ts +0 -87
- package/src/utils.ts +0 -124
package/src/list.ts
DELETED
@@ -1,987 +0,0 @@
|
|
1
|
-
import { RefInt, TernaryTreeKind, TernaryTreeList, TernaryTreeListTheBranch } from "./types";
|
2
|
-
import {} from "./map";
|
3
|
-
import { dataEqual, divideTernarySizes, roughIntPow } from "./utils";
|
4
|
-
|
5
|
-
// just get, will not compute recursively
|
6
|
-
export function getDepth<T>(tree: TernaryTreeList<T>): number {
|
7
|
-
if (tree == null) return 0;
|
8
|
-
switch (tree.kind) {
|
9
|
-
case TernaryTreeKind.ternaryTreeLeaf:
|
10
|
-
return 1;
|
11
|
-
case TernaryTreeKind.ternaryTreeBranch:
|
12
|
-
return tree.depth;
|
13
|
-
}
|
14
|
-
}
|
15
|
-
|
16
|
-
let emptyBranch: TernaryTreeList<any> = null as any;
|
17
|
-
|
18
|
-
let isEmptyBranch = (x: TernaryTreeList<any>) => {
|
19
|
-
if (x == null) {
|
20
|
-
return true;
|
21
|
-
}
|
22
|
-
return x.size == 0;
|
23
|
-
};
|
24
|
-
|
25
|
-
function decideParentDepth<T>(...xs: Array<TernaryTreeList<T>>): number {
|
26
|
-
let depth = 0;
|
27
|
-
for (let i = 0; i < xs.length; i++) {
|
28
|
-
let x = xs[i];
|
29
|
-
let y = getDepth(x);
|
30
|
-
if (y > depth) {
|
31
|
-
depth = y;
|
32
|
-
}
|
33
|
-
}
|
34
|
-
return depth + 1;
|
35
|
-
}
|
36
|
-
|
37
|
-
export function makeTernaryTreeList<T>(size: number, offset: number, xs: /* var */ Array<TernaryTreeList<T>>): TernaryTreeList<T> {
|
38
|
-
switch (size) {
|
39
|
-
case 0: {
|
40
|
-
return { kind: TernaryTreeKind.ternaryTreeBranch, size: 0, depth: 1, left: emptyBranch, middle: emptyBranch, right: emptyBranch } as TernaryTreeList<T>;
|
41
|
-
}
|
42
|
-
case 1:
|
43
|
-
return xs[offset];
|
44
|
-
case 2: {
|
45
|
-
let left = xs[offset];
|
46
|
-
let middle = xs[offset + 1];
|
47
|
-
let result: TernaryTreeList<T> = {
|
48
|
-
kind: TernaryTreeKind.ternaryTreeBranch,
|
49
|
-
size: listLen(left) + listLen(middle),
|
50
|
-
left: left,
|
51
|
-
middle: middle,
|
52
|
-
right: emptyBranch,
|
53
|
-
depth: decideParentDepth(left, middle),
|
54
|
-
};
|
55
|
-
return result;
|
56
|
-
}
|
57
|
-
case 3: {
|
58
|
-
let left = xs[offset];
|
59
|
-
let middle = xs[offset + 1];
|
60
|
-
let right = xs[offset + 2];
|
61
|
-
let result: TernaryTreeList<T> = {
|
62
|
-
kind: TernaryTreeKind.ternaryTreeBranch,
|
63
|
-
size: listLen(left) + listLen(middle) + listLen(right),
|
64
|
-
left: left,
|
65
|
-
middle: middle,
|
66
|
-
right: right,
|
67
|
-
depth: decideParentDepth(left, middle, right),
|
68
|
-
};
|
69
|
-
return result;
|
70
|
-
}
|
71
|
-
default: {
|
72
|
-
let divided = divideTernarySizes(size);
|
73
|
-
|
74
|
-
let left = makeTernaryTreeList(divided.left, offset, xs);
|
75
|
-
let middle = makeTernaryTreeList(divided.middle, offset + divided.left, xs);
|
76
|
-
let right = makeTernaryTreeList(divided.right, offset + divided.left + divided.middle, xs);
|
77
|
-
let result: TernaryTreeList<T> = {
|
78
|
-
kind: TernaryTreeKind.ternaryTreeBranch,
|
79
|
-
size: listLen(left) + listLen(middle) + listLen(right),
|
80
|
-
depth: decideParentDepth(left, middle, right),
|
81
|
-
left: left,
|
82
|
-
middle: middle,
|
83
|
-
right: right,
|
84
|
-
};
|
85
|
-
return result;
|
86
|
-
}
|
87
|
-
}
|
88
|
-
}
|
89
|
-
|
90
|
-
export function initTernaryTreeList<T>(xs: Array<T>): TernaryTreeList<T> {
|
91
|
-
let ys = new Array<TernaryTreeList<T>>(xs.length);
|
92
|
-
let size = xs.length;
|
93
|
-
for (let idx = 0; idx < size; idx++) {
|
94
|
-
let x = xs[idx];
|
95
|
-
ys[idx] = { kind: TernaryTreeKind.ternaryTreeLeaf, size: 1, value: x };
|
96
|
-
}
|
97
|
-
return makeTernaryTreeList(xs.length, 0, ys);
|
98
|
-
}
|
99
|
-
|
100
|
-
export function initEmptyTernaryTreeList<T>(): TernaryTreeList<T> {
|
101
|
-
return { kind: TernaryTreeKind.ternaryTreeBranch, size: 0, depth: 1, middle: emptyBranch, left: emptyBranch, right: emptyBranch };
|
102
|
-
}
|
103
|
-
|
104
|
-
export function listToString<T>(tree: TernaryTreeList<T>): string {
|
105
|
-
return `TernaryTreeList[${tree.size}, ...]`;
|
106
|
-
}
|
107
|
-
|
108
|
-
export function listLen<T>(tree: TernaryTreeList<T>): number {
|
109
|
-
if (tree == null) {
|
110
|
-
return 0;
|
111
|
-
} else {
|
112
|
-
return tree.size;
|
113
|
-
}
|
114
|
-
}
|
115
|
-
|
116
|
-
function isLeaf<T>(tree: TernaryTreeList<T>): boolean {
|
117
|
-
return tree.kind === TernaryTreeKind.ternaryTreeLeaf;
|
118
|
-
}
|
119
|
-
|
120
|
-
function isBranch<T>(tree: TernaryTreeList<T>): boolean {
|
121
|
-
return tree.kind === TernaryTreeKind.ternaryTreeBranch;
|
122
|
-
}
|
123
|
-
|
124
|
-
export function formatListInline<T>(tree: TernaryTreeList<T>): string {
|
125
|
-
if (tree == null) {
|
126
|
-
return "_";
|
127
|
-
}
|
128
|
-
switch (tree.kind) {
|
129
|
-
case TernaryTreeKind.ternaryTreeLeaf:
|
130
|
-
return `${tree.value}`;
|
131
|
-
case TernaryTreeKind.ternaryTreeBranch:
|
132
|
-
return "(" + formatListInline(tree.left) + " " + formatListInline(tree.middle) + " " + formatListInline(tree.right) + ")";
|
133
|
-
// "(" & tree.left.formatListInline & " " & tree.middle.formatListInline & " " & tree.right.formatListInline & ")@{tree.depth} " & "{tree.left.getDepth} {tree.middle.getDepth} {tree.right.getDepth}..."
|
134
|
-
}
|
135
|
-
}
|
136
|
-
|
137
|
-
export function* listToItems<T>(tree: TernaryTreeList<T>): Generator<T> {
|
138
|
-
if (tree != null) {
|
139
|
-
switch (tree.kind) {
|
140
|
-
case TernaryTreeKind.ternaryTreeLeaf: {
|
141
|
-
yield tree.value;
|
142
|
-
break;
|
143
|
-
}
|
144
|
-
case TernaryTreeKind.ternaryTreeBranch: {
|
145
|
-
if (tree.left != null) {
|
146
|
-
for (let x of listToItems(tree.left)) {
|
147
|
-
yield x;
|
148
|
-
}
|
149
|
-
}
|
150
|
-
if (tree.middle != null) {
|
151
|
-
for (let x of listToItems(tree.middle)) {
|
152
|
-
yield x;
|
153
|
-
}
|
154
|
-
}
|
155
|
-
if (tree.right != null) {
|
156
|
-
for (let x of listToItems(tree.right)) {
|
157
|
-
yield x;
|
158
|
-
}
|
159
|
-
}
|
160
|
-
break;
|
161
|
-
}
|
162
|
-
}
|
163
|
-
}
|
164
|
-
}
|
165
|
-
|
166
|
-
// returns -1 if (not foun)
|
167
|
-
export function findIndex<T>(tree: TernaryTreeList<T>, f: (x: T) => boolean): number {
|
168
|
-
if (tree == null) {
|
169
|
-
return -1;
|
170
|
-
}
|
171
|
-
switch (tree.kind) {
|
172
|
-
case TernaryTreeKind.ternaryTreeLeaf: {
|
173
|
-
if (f(tree.value)) {
|
174
|
-
return 0;
|
175
|
-
} else {
|
176
|
-
return -1;
|
177
|
-
}
|
178
|
-
}
|
179
|
-
case TernaryTreeKind.ternaryTreeBranch: {
|
180
|
-
let tryLeft = findIndex(tree.left, f);
|
181
|
-
if (tryLeft >= 0) {
|
182
|
-
return tryLeft;
|
183
|
-
}
|
184
|
-
let tryMiddle = findIndex(tree.middle, f);
|
185
|
-
if (tryMiddle >= 0) {
|
186
|
-
return tryMiddle + listLen(tree.left);
|
187
|
-
}
|
188
|
-
let tryRight = findIndex(tree.right, f);
|
189
|
-
if (tryRight >= 0) {
|
190
|
-
return tryRight + listLen(tree.left) + listLen(tree.middle);
|
191
|
-
}
|
192
|
-
return -1;
|
193
|
-
}
|
194
|
-
}
|
195
|
-
}
|
196
|
-
|
197
|
-
// returns -1 if (not foun)
|
198
|
-
export function indexOf<T>(tree: TernaryTreeList<T>, item: T): number {
|
199
|
-
if (tree == null) {
|
200
|
-
return -1;
|
201
|
-
}
|
202
|
-
switch (tree.kind) {
|
203
|
-
case TernaryTreeKind.ternaryTreeLeaf:
|
204
|
-
if (dataEqual(item, tree.value)) {
|
205
|
-
return 0;
|
206
|
-
}
|
207
|
-
default:
|
208
|
-
return -1;
|
209
|
-
case TernaryTreeKind.ternaryTreeBranch:
|
210
|
-
let tryLeft = indexOf(tree.left, item);
|
211
|
-
if (tryLeft >= 0) {
|
212
|
-
return tryLeft;
|
213
|
-
}
|
214
|
-
let tryMiddle = indexOf(tree.middle, item);
|
215
|
-
if (tryMiddle >= 0) {
|
216
|
-
return tryMiddle + listLen(tree.left);
|
217
|
-
}
|
218
|
-
let tryRight = indexOf(tree.right, item);
|
219
|
-
if (tryRight >= 0) {
|
220
|
-
return tryRight + listLen(tree.left) + listLen(tree.middle);
|
221
|
-
}
|
222
|
-
return -1;
|
223
|
-
}
|
224
|
-
}
|
225
|
-
|
226
|
-
function writeLeavesArray<T>(tree: TernaryTreeList<T>, acc: /* var */ Array<TernaryTreeList<T>>, idx: RefInt): void {
|
227
|
-
if (tree == null) {
|
228
|
-
//
|
229
|
-
} else {
|
230
|
-
switch (tree.kind) {
|
231
|
-
case TernaryTreeKind.ternaryTreeLeaf: {
|
232
|
-
acc[idx.value] = tree;
|
233
|
-
idx.value = idx.value + 1;
|
234
|
-
break;
|
235
|
-
}
|
236
|
-
case TernaryTreeKind.ternaryTreeBranch: {
|
237
|
-
if (tree.left != null) {
|
238
|
-
writeLeavesArray(tree.left, acc, idx);
|
239
|
-
}
|
240
|
-
if (tree.middle != null) {
|
241
|
-
writeLeavesArray(tree.middle, acc, idx);
|
242
|
-
}
|
243
|
-
if (tree.right != null) {
|
244
|
-
writeLeavesArray(tree.right, acc, idx);
|
245
|
-
}
|
246
|
-
break;
|
247
|
-
}
|
248
|
-
default: {
|
249
|
-
throw new Error("Unknown");
|
250
|
-
}
|
251
|
-
}
|
252
|
-
}
|
253
|
-
}
|
254
|
-
|
255
|
-
function toLeavesArray<T>(tree: TernaryTreeList<T>): Array<TernaryTreeList<T>> {
|
256
|
-
let acc = new Array<TernaryTreeList<T>>(listLen(tree));
|
257
|
-
let counter: RefInt = { value: 0 };
|
258
|
-
writeLeavesArray(tree, acc, counter);
|
259
|
-
return acc;
|
260
|
-
}
|
261
|
-
|
262
|
-
export function* indexToItems<T>(tree: TernaryTreeList<T>): Generator<T> {
|
263
|
-
for (let idx = 0; idx < listLen(tree); idx++) {
|
264
|
-
yield listGet(tree, idx);
|
265
|
-
}
|
266
|
-
}
|
267
|
-
|
268
|
-
export function* listToPairs<T>(tree: TernaryTreeList<T>): Generator<[number, T]> {
|
269
|
-
let idx = 0;
|
270
|
-
for (let x of listToItems(tree)) {
|
271
|
-
yield [idx, x];
|
272
|
-
idx = idx + 1;
|
273
|
-
}
|
274
|
-
}
|
275
|
-
|
276
|
-
export function listGet<T>(originalTree: TernaryTreeList<T>, originalIdx: number): T {
|
277
|
-
let tree = originalTree;
|
278
|
-
let idx = originalIdx;
|
279
|
-
while (tree != null) {
|
280
|
-
if (idx < 0) {
|
281
|
-
throw new Error("Cannot index negative number");
|
282
|
-
}
|
283
|
-
|
284
|
-
if (tree.kind === TernaryTreeKind.ternaryTreeLeaf) {
|
285
|
-
if (idx === 0) {
|
286
|
-
return tree.value;
|
287
|
-
} else {
|
288
|
-
throw new Error(`Cannot get from leaf with index ${idx}`);
|
289
|
-
}
|
290
|
-
}
|
291
|
-
|
292
|
-
if (idx > tree.size - 1) {
|
293
|
-
throw new Error("Index too large");
|
294
|
-
}
|
295
|
-
|
296
|
-
let leftSize = tree.left == null ? 0 : tree.left.size;
|
297
|
-
let middleSize = tree.middle == null ? 0 : tree.middle.size;
|
298
|
-
let rightSize = tree.right == null ? 0 : tree.right.size;
|
299
|
-
|
300
|
-
if (leftSize + middleSize + rightSize !== tree.size) {
|
301
|
-
throw new Error("tree.size does not match sum case branch sizes");
|
302
|
-
}
|
303
|
-
|
304
|
-
if (idx <= leftSize - 1) {
|
305
|
-
tree = tree.left;
|
306
|
-
} else if (idx <= leftSize + middleSize - 1) {
|
307
|
-
tree = tree.middle;
|
308
|
-
idx = idx - leftSize;
|
309
|
-
} else {
|
310
|
-
tree = tree.right;
|
311
|
-
idx = idx - leftSize - middleSize;
|
312
|
-
}
|
313
|
-
}
|
314
|
-
|
315
|
-
throw new Error(`Failed to get ${idx}`);
|
316
|
-
}
|
317
|
-
|
318
|
-
export function first<T>(tree: TernaryTreeList<T>): T {
|
319
|
-
if (listLen(tree) > 0) {
|
320
|
-
return listGet(tree, 0);
|
321
|
-
} else {
|
322
|
-
throw new Error("Cannot get from empty list");
|
323
|
-
}
|
324
|
-
}
|
325
|
-
|
326
|
-
export function last<T>(tree: TernaryTreeList<T>): T {
|
327
|
-
if (listLen(tree) > 0) {
|
328
|
-
return listGet(tree, listLen(tree) - 1);
|
329
|
-
} else {
|
330
|
-
throw new Error("Cannot get from empty list");
|
331
|
-
}
|
332
|
-
}
|
333
|
-
|
334
|
-
export function assocList<T>(tree: TernaryTreeList<T>, idx: number, item: T): TernaryTreeList<T> {
|
335
|
-
if (idx < 0) {
|
336
|
-
throw new Error("Cannot index negative number");
|
337
|
-
}
|
338
|
-
if (idx > tree.size - 1) {
|
339
|
-
throw new Error("Index too large");
|
340
|
-
}
|
341
|
-
|
342
|
-
if (tree.kind === TernaryTreeKind.ternaryTreeLeaf) {
|
343
|
-
if (idx === 0) {
|
344
|
-
return { kind: TernaryTreeKind.ternaryTreeLeaf, size: 1, value: item } as TernaryTreeList<T>;
|
345
|
-
} else {
|
346
|
-
throw new Error(`Cannot get from leaf with index ${idx}`);
|
347
|
-
}
|
348
|
-
}
|
349
|
-
|
350
|
-
let leftSize = listLen(tree.left);
|
351
|
-
let middleSize = listLen(tree.middle);
|
352
|
-
let rightSize = listLen(tree.right);
|
353
|
-
|
354
|
-
if (leftSize + middleSize + rightSize !== tree.size) throw new Error("tree.size does not match sum case branch sizes");
|
355
|
-
|
356
|
-
if (idx <= leftSize - 1) {
|
357
|
-
let changedBranch = assocList(tree.left, idx, item);
|
358
|
-
let result: TernaryTreeList<T> = {
|
359
|
-
kind: TernaryTreeKind.ternaryTreeBranch,
|
360
|
-
size: tree.size,
|
361
|
-
depth: decideParentDepth(changedBranch, tree.middle, tree.right),
|
362
|
-
left: changedBranch,
|
363
|
-
middle: tree.middle,
|
364
|
-
right: tree.right,
|
365
|
-
};
|
366
|
-
return result;
|
367
|
-
} else if (idx <= leftSize + middleSize - 1) {
|
368
|
-
let changedBranch = assocList(tree.middle, idx - leftSize, item);
|
369
|
-
let result: TernaryTreeList<T> = {
|
370
|
-
kind: TernaryTreeKind.ternaryTreeBranch,
|
371
|
-
size: tree.size,
|
372
|
-
depth: decideParentDepth(tree.left, changedBranch, tree.right),
|
373
|
-
left: tree.left,
|
374
|
-
middle: changedBranch,
|
375
|
-
right: tree.right,
|
376
|
-
};
|
377
|
-
return result;
|
378
|
-
} else {
|
379
|
-
let changedBranch = assocList(tree.right, idx - leftSize - middleSize, item);
|
380
|
-
let result: TernaryTreeList<T> = {
|
381
|
-
kind: TernaryTreeKind.ternaryTreeBranch,
|
382
|
-
size: tree.size,
|
383
|
-
depth: decideParentDepth(tree.left, tree.middle, changedBranch),
|
384
|
-
left: tree.left,
|
385
|
-
middle: tree.middle,
|
386
|
-
right: changedBranch,
|
387
|
-
};
|
388
|
-
return result;
|
389
|
-
}
|
390
|
-
}
|
391
|
-
|
392
|
-
export function dissocList<T>(tree: TernaryTreeList<T>, idx: number): TernaryTreeList<T> {
|
393
|
-
if (tree == null) {
|
394
|
-
throw new Error("dissoc does not work on null");
|
395
|
-
}
|
396
|
-
|
397
|
-
if (idx < 0) {
|
398
|
-
throw new Error(`Index is negative ${idx}`);
|
399
|
-
}
|
400
|
-
|
401
|
-
if (listLen(tree) === 0) {
|
402
|
-
throw new Error("Cannot remove from empty list");
|
403
|
-
}
|
404
|
-
|
405
|
-
if (idx > listLen(tree) - 1) {
|
406
|
-
throw new Error(`Index too large ${idx}`);
|
407
|
-
}
|
408
|
-
|
409
|
-
if (listLen(tree) === 1) {
|
410
|
-
return emptyBranch;
|
411
|
-
}
|
412
|
-
|
413
|
-
if (tree.kind === TernaryTreeKind.ternaryTreeLeaf) {
|
414
|
-
throw new Error("dissoc should be handled at branches");
|
415
|
-
}
|
416
|
-
|
417
|
-
let leftSize = listLen(tree.left);
|
418
|
-
let middleSize = listLen(tree.middle);
|
419
|
-
let rightSize = listLen(tree.right);
|
420
|
-
|
421
|
-
if (leftSize + middleSize + rightSize !== tree.size) {
|
422
|
-
throw new Error("tree.size does not match sum from branch sizes");
|
423
|
-
}
|
424
|
-
|
425
|
-
let result: TernaryTreeList<T> = emptyBranch;
|
426
|
-
|
427
|
-
if (idx <= leftSize - 1) {
|
428
|
-
let changedBranch = dissocList(tree.left, idx);
|
429
|
-
if (changedBranch == null || changedBranch.size === 0) {
|
430
|
-
result = {
|
431
|
-
kind: TernaryTreeKind.ternaryTreeBranch,
|
432
|
-
size: tree.size - 1,
|
433
|
-
depth: decideParentDepth(tree.middle, tree.right),
|
434
|
-
left: tree.middle,
|
435
|
-
middle: tree.right,
|
436
|
-
right: emptyBranch,
|
437
|
-
};
|
438
|
-
} else {
|
439
|
-
result = {
|
440
|
-
kind: TernaryTreeKind.ternaryTreeBranch,
|
441
|
-
size: tree.size - 1,
|
442
|
-
depth: decideParentDepth(changedBranch, tree.middle, tree.right),
|
443
|
-
left: changedBranch,
|
444
|
-
middle: tree.middle,
|
445
|
-
right: tree.right,
|
446
|
-
};
|
447
|
-
}
|
448
|
-
} else if (idx <= leftSize + middleSize - 1) {
|
449
|
-
let changedBranch = dissocList(tree.middle, idx - leftSize);
|
450
|
-
if (changedBranch == null || changedBranch.size === 0) {
|
451
|
-
result = {
|
452
|
-
kind: TernaryTreeKind.ternaryTreeBranch,
|
453
|
-
size: tree.size - 1,
|
454
|
-
depth: decideParentDepth(tree.left, changedBranch, tree.right),
|
455
|
-
left: tree.left,
|
456
|
-
middle: tree.right,
|
457
|
-
right: emptyBranch,
|
458
|
-
};
|
459
|
-
} else {
|
460
|
-
result = {
|
461
|
-
kind: TernaryTreeKind.ternaryTreeBranch,
|
462
|
-
size: tree.size - 1,
|
463
|
-
depth: decideParentDepth(tree.left, changedBranch, tree.right),
|
464
|
-
left: tree.left,
|
465
|
-
middle: changedBranch,
|
466
|
-
right: tree.right,
|
467
|
-
};
|
468
|
-
}
|
469
|
-
} else {
|
470
|
-
let changedBranch = dissocList(tree.right, idx - leftSize - middleSize);
|
471
|
-
if (changedBranch == null || changedBranch.size === 0) {
|
472
|
-
changedBranch = emptyBranch;
|
473
|
-
}
|
474
|
-
result = {
|
475
|
-
kind: TernaryTreeKind.ternaryTreeBranch,
|
476
|
-
size: tree.size - 1,
|
477
|
-
depth: decideParentDepth(tree.left, tree.middle, changedBranch),
|
478
|
-
left: tree.left,
|
479
|
-
middle: tree.middle,
|
480
|
-
right: changedBranch,
|
481
|
-
};
|
482
|
-
}
|
483
|
-
if (result.middle == null) {
|
484
|
-
return result.left;
|
485
|
-
}
|
486
|
-
return result;
|
487
|
-
}
|
488
|
-
|
489
|
-
export function rest<T>(tree: TernaryTreeList<T>): TernaryTreeList<T> {
|
490
|
-
if (tree == null) {
|
491
|
-
throw new Error("Cannot call rest on null");
|
492
|
-
}
|
493
|
-
if (listLen(tree) < 1) {
|
494
|
-
throw new Error("Cannot call rest on empty list");
|
495
|
-
}
|
496
|
-
|
497
|
-
return dissocList(tree, 0);
|
498
|
-
}
|
499
|
-
|
500
|
-
export function butlast<T>(tree: TernaryTreeList<T>): TernaryTreeList<T> {
|
501
|
-
if (tree == null) {
|
502
|
-
throw new Error("Cannot call butlast on null");
|
503
|
-
}
|
504
|
-
if (listLen(tree) < 1) {
|
505
|
-
throw new Error("Cannot call butlast on empty list");
|
506
|
-
}
|
507
|
-
|
508
|
-
return dissocList(tree, listLen(tree) - 1);
|
509
|
-
}
|
510
|
-
|
511
|
-
export function insert<T>(tree: TernaryTreeList<T>, idx: number, item: T, after: boolean = false): TernaryTreeList<T> {
|
512
|
-
if (tree == null) {
|
513
|
-
throw new Error("Cannot insert into null");
|
514
|
-
}
|
515
|
-
if (listLen(tree) === 0) {
|
516
|
-
throw new Error("Empty node is not a correct position for inserting");
|
517
|
-
}
|
518
|
-
|
519
|
-
if (tree.kind === TernaryTreeKind.ternaryTreeLeaf) {
|
520
|
-
if (after) {
|
521
|
-
let result: TernaryTreeList<T> = {
|
522
|
-
kind: TernaryTreeKind.ternaryTreeBranch,
|
523
|
-
depth: getDepth(tree) + 1,
|
524
|
-
size: 2,
|
525
|
-
left: tree,
|
526
|
-
middle: { kind: TernaryTreeKind.ternaryTreeLeaf, size: 1, value: item } as TernaryTreeList<T>,
|
527
|
-
right: emptyBranch,
|
528
|
-
};
|
529
|
-
return result;
|
530
|
-
} else {
|
531
|
-
let result: TernaryTreeList<T> = {
|
532
|
-
kind: TernaryTreeKind.ternaryTreeBranch,
|
533
|
-
depth: getDepth(tree) + 1,
|
534
|
-
size: 2,
|
535
|
-
left: { kind: TernaryTreeKind.ternaryTreeLeaf, size: 1, value: item } as TernaryTreeList<T>,
|
536
|
-
middle: tree,
|
537
|
-
right: emptyBranch,
|
538
|
-
};
|
539
|
-
return result;
|
540
|
-
}
|
541
|
-
}
|
542
|
-
|
543
|
-
if (listLen(tree) === 1) {
|
544
|
-
if (after) {
|
545
|
-
// in compact mode, values placed at left
|
546
|
-
let result: TernaryTreeList<T> = {
|
547
|
-
kind: TernaryTreeKind.ternaryTreeBranch,
|
548
|
-
size: 2,
|
549
|
-
depth: 2,
|
550
|
-
left: tree.left,
|
551
|
-
middle: { kind: TernaryTreeKind.ternaryTreeLeaf, size: 1, value: item } as TernaryTreeList<T>,
|
552
|
-
right: emptyBranch,
|
553
|
-
};
|
554
|
-
return result;
|
555
|
-
} else {
|
556
|
-
let result: TernaryTreeList<T> = {
|
557
|
-
kind: TernaryTreeKind.ternaryTreeBranch,
|
558
|
-
size: 2,
|
559
|
-
depth: getDepth(tree.middle) + 1,
|
560
|
-
left: { kind: TernaryTreeKind.ternaryTreeLeaf, size: 1, value: item } as TernaryTreeList<T>,
|
561
|
-
middle: tree.left,
|
562
|
-
right: emptyBranch,
|
563
|
-
};
|
564
|
-
return result;
|
565
|
-
}
|
566
|
-
}
|
567
|
-
|
568
|
-
if (listLen(tree) === 2 && tree.middle != null) {
|
569
|
-
if (after) {
|
570
|
-
if (idx === 0) {
|
571
|
-
let result: TernaryTreeList<T> = {
|
572
|
-
kind: TernaryTreeKind.ternaryTreeBranch,
|
573
|
-
size: 3,
|
574
|
-
depth: 2,
|
575
|
-
left: tree.left,
|
576
|
-
middle: { kind: TernaryTreeKind.ternaryTreeLeaf, size: 1, value: item } as TernaryTreeList<T>,
|
577
|
-
right: tree.middle,
|
578
|
-
};
|
579
|
-
return result;
|
580
|
-
}
|
581
|
-
if (idx === 1) {
|
582
|
-
let result: TernaryTreeList<T> = {
|
583
|
-
kind: TernaryTreeKind.ternaryTreeBranch,
|
584
|
-
size: 3,
|
585
|
-
depth: 2,
|
586
|
-
left: tree.left,
|
587
|
-
middle: tree.middle,
|
588
|
-
right: { kind: TernaryTreeKind.ternaryTreeLeaf, size: 1, value: item } as TernaryTreeList<T>,
|
589
|
-
};
|
590
|
-
return result;
|
591
|
-
} else {
|
592
|
-
throw new Error("cannot insert after position 2 since only 2 elements here");
|
593
|
-
}
|
594
|
-
} else {
|
595
|
-
if (idx === 0) {
|
596
|
-
let result: TernaryTreeList<T> = {
|
597
|
-
kind: TernaryTreeKind.ternaryTreeBranch,
|
598
|
-
size: 3,
|
599
|
-
depth: 2,
|
600
|
-
left: { kind: TernaryTreeKind.ternaryTreeLeaf, size: 1, value: item } as TernaryTreeList<T>,
|
601
|
-
middle: tree.left,
|
602
|
-
right: tree.middle,
|
603
|
-
};
|
604
|
-
return result;
|
605
|
-
} else if (idx === 1) {
|
606
|
-
let result: TernaryTreeList<T> = {
|
607
|
-
kind: TernaryTreeKind.ternaryTreeBranch,
|
608
|
-
size: 3,
|
609
|
-
depth: 2,
|
610
|
-
left: tree.left,
|
611
|
-
middle: { kind: TernaryTreeKind.ternaryTreeLeaf, size: 1, value: item } as TernaryTreeList<T>,
|
612
|
-
right: tree.middle,
|
613
|
-
};
|
614
|
-
return result;
|
615
|
-
} else {
|
616
|
-
throw new Error("cannot insert before position 2 since only 2 elements here");
|
617
|
-
}
|
618
|
-
}
|
619
|
-
}
|
620
|
-
|
621
|
-
let leftSize = listLen(tree.left);
|
622
|
-
let middleSize = listLen(tree.middle);
|
623
|
-
let rightSize = listLen(tree.right);
|
624
|
-
|
625
|
-
if (leftSize + middleSize + rightSize !== tree.size) {
|
626
|
-
throw new Error("tree.size does not match sum case branch sizes");
|
627
|
-
}
|
628
|
-
|
629
|
-
// echo "picking: ", idx, " ", leftSize, " ", middleSize, " ", rightSize
|
630
|
-
|
631
|
-
if (idx === 0 && !after) {
|
632
|
-
if (listLen(tree.left) >= listLen(tree.middle) && listLen(tree.left) >= listLen(tree.right)) {
|
633
|
-
let result: TernaryTreeList<T> = {
|
634
|
-
kind: TernaryTreeKind.ternaryTreeBranch,
|
635
|
-
size: tree.size + 1,
|
636
|
-
depth: tree.depth + 1,
|
637
|
-
left: { kind: TernaryTreeKind.ternaryTreeLeaf, size: 1, value: item } as TernaryTreeList<T>,
|
638
|
-
middle: tree,
|
639
|
-
right: emptyBranch,
|
640
|
-
};
|
641
|
-
return result;
|
642
|
-
}
|
643
|
-
}
|
644
|
-
|
645
|
-
if (idx === listLen(tree) - 1 && after) {
|
646
|
-
if (listLen(tree.right) >= listLen(tree.middle) && listLen(tree.right) >= listLen(tree.left)) {
|
647
|
-
let result: TernaryTreeList<T> = {
|
648
|
-
kind: TernaryTreeKind.ternaryTreeBranch,
|
649
|
-
size: tree.size + 1,
|
650
|
-
depth: tree.depth + 1,
|
651
|
-
left: tree,
|
652
|
-
middle: { kind: TernaryTreeKind.ternaryTreeLeaf, size: 1, value: item } as TernaryTreeList<T>,
|
653
|
-
right: emptyBranch,
|
654
|
-
};
|
655
|
-
return result;
|
656
|
-
}
|
657
|
-
}
|
658
|
-
|
659
|
-
if (after && idx === listLen(tree) - 1 && rightSize === 0 && middleSize >= leftSize) {
|
660
|
-
let result: TernaryTreeList<T> = {
|
661
|
-
kind: TernaryTreeKind.ternaryTreeBranch,
|
662
|
-
size: tree.size + 1,
|
663
|
-
depth: tree.depth,
|
664
|
-
left: tree.left,
|
665
|
-
middle: tree.middle,
|
666
|
-
right: { kind: TernaryTreeKind.ternaryTreeLeaf, size: 1, value: item } as TernaryTreeList<T>,
|
667
|
-
};
|
668
|
-
return result;
|
669
|
-
}
|
670
|
-
|
671
|
-
if (!after && idx === 0 && rightSize === 0 && middleSize >= rightSize) {
|
672
|
-
let result: TernaryTreeList<T> = {
|
673
|
-
kind: TernaryTreeKind.ternaryTreeBranch,
|
674
|
-
size: tree.size + 1,
|
675
|
-
depth: tree.depth,
|
676
|
-
left: { kind: TernaryTreeKind.ternaryTreeLeaf, size: 1, value: item } as TernaryTreeList<T>,
|
677
|
-
middle: tree.left,
|
678
|
-
right: tree.middle,
|
679
|
-
};
|
680
|
-
return result;
|
681
|
-
}
|
682
|
-
|
683
|
-
if (idx <= leftSize - 1) {
|
684
|
-
let changedBranch = insert(tree.left, idx, item, after);
|
685
|
-
|
686
|
-
let result: TernaryTreeList<T> = {
|
687
|
-
kind: TernaryTreeKind.ternaryTreeBranch,
|
688
|
-
size: tree.size + 1,
|
689
|
-
depth: decideParentDepth(changedBranch, tree.middle, tree.right),
|
690
|
-
left: changedBranch,
|
691
|
-
middle: tree.middle,
|
692
|
-
right: tree.right,
|
693
|
-
};
|
694
|
-
return result;
|
695
|
-
} else if (idx <= leftSize + middleSize - 1) {
|
696
|
-
let changedBranch = insert(tree.middle, idx - leftSize, item, after);
|
697
|
-
|
698
|
-
let result: TernaryTreeList<T> = {
|
699
|
-
kind: TernaryTreeKind.ternaryTreeBranch,
|
700
|
-
size: tree.size + 1,
|
701
|
-
depth: decideParentDepth(tree.left, changedBranch, tree.right),
|
702
|
-
left: tree.left,
|
703
|
-
middle: changedBranch,
|
704
|
-
right: tree.right,
|
705
|
-
};
|
706
|
-
|
707
|
-
return result;
|
708
|
-
} else {
|
709
|
-
let changedBranch = insert(tree.right, idx - leftSize - middleSize, item, after);
|
710
|
-
|
711
|
-
let result: TernaryTreeList<T> = {
|
712
|
-
kind: TernaryTreeKind.ternaryTreeBranch,
|
713
|
-
size: tree.size + 1,
|
714
|
-
depth: decideParentDepth(tree.left, tree.middle, changedBranch),
|
715
|
-
left: tree.left,
|
716
|
-
middle: tree.middle,
|
717
|
-
right: changedBranch,
|
718
|
-
};
|
719
|
-
return result;
|
720
|
-
}
|
721
|
-
}
|
722
|
-
|
723
|
-
export function assocBefore<T>(tree: TernaryTreeList<T>, idx: number, item: T, after: boolean = false): TernaryTreeList<T> {
|
724
|
-
return insert(tree, idx, item, false);
|
725
|
-
}
|
726
|
-
|
727
|
-
export function assocAfter<T>(tree: TernaryTreeList<T>, idx: number, item: T, after: boolean = false): TernaryTreeList<T> {
|
728
|
-
return insert(tree, idx, item, true);
|
729
|
-
}
|
730
|
-
|
731
|
-
// this function mutates original tree to make it more balanced
|
732
|
-
export function forceListInplaceBalancing<T>(tree: TernaryTreeList<T>): void {
|
733
|
-
if (tree.kind === TernaryTreeKind.ternaryTreeBranch) {
|
734
|
-
// echo "Force inplace balancing case list: ", tree.size
|
735
|
-
let ys = toLeavesArray(tree);
|
736
|
-
let newTree = makeTernaryTreeList(ys.length, 0, ys) as TernaryTreeListTheBranch<T>;
|
737
|
-
// let newTree = initTernaryTreeList(ys)
|
738
|
-
tree.left = newTree.left;
|
739
|
-
tree.middle = newTree.middle;
|
740
|
-
tree.right = newTree.right;
|
741
|
-
tree.depth = decideParentDepth(tree.left, tree.middle, tree.right);
|
742
|
-
} else {
|
743
|
-
//
|
744
|
-
}
|
745
|
-
}
|
746
|
-
|
747
|
-
// TODO, need better strategy for detecting
|
748
|
-
function maybeReblance<T>(tree: TernaryTreeList<T>): void {
|
749
|
-
let currentDepth = getDepth(tree);
|
750
|
-
if (currentDepth > 50) {
|
751
|
-
if (roughIntPow(3, currentDepth - 50) > tree.size) {
|
752
|
-
forceListInplaceBalancing(tree);
|
753
|
-
}
|
754
|
-
}
|
755
|
-
}
|
756
|
-
|
757
|
-
export function prepend<T>(tree: TernaryTreeList<T>, item: T, disableBalancing: boolean = false): TernaryTreeList<T> {
|
758
|
-
if (tree == null || listLen(tree) === 0) {
|
759
|
-
return { kind: TernaryTreeKind.ternaryTreeLeaf, size: 1, value: item } as TernaryTreeList<T>;
|
760
|
-
}
|
761
|
-
let result = insert(tree, 0, item, false);
|
762
|
-
|
763
|
-
if (!disableBalancing) {
|
764
|
-
maybeReblance(result);
|
765
|
-
}
|
766
|
-
return result;
|
767
|
-
}
|
768
|
-
|
769
|
-
export function append<T>(tree: TernaryTreeList<T>, item: T, disableBalancing: boolean = false): TernaryTreeList<T> {
|
770
|
-
if (tree == null || listLen(tree) === 0) {
|
771
|
-
return { kind: TernaryTreeKind.ternaryTreeLeaf, size: 1, value: item } as TernaryTreeList<T>;
|
772
|
-
}
|
773
|
-
let result = insert(tree, listLen(tree) - 1, item, true);
|
774
|
-
|
775
|
-
if (!disableBalancing) {
|
776
|
-
maybeReblance(result);
|
777
|
-
}
|
778
|
-
return result;
|
779
|
-
}
|
780
|
-
|
781
|
-
export function concat<T>(...xsGroups: Array<TernaryTreeList<T>>): TernaryTreeList<T> {
|
782
|
-
xsGroups = xsGroups.filter((xs) => listLen(xs) > 0);
|
783
|
-
let result = makeTernaryTreeList(xsGroups.length, 0, xsGroups);
|
784
|
-
maybeReblance(result);
|
785
|
-
return result;
|
786
|
-
}
|
787
|
-
|
788
|
-
export function sameListShape<T>(xs: TernaryTreeList<T>, ys: TernaryTreeList<T>): boolean {
|
789
|
-
if (xs == null) {
|
790
|
-
if (ys == null) {
|
791
|
-
return true;
|
792
|
-
} else {
|
793
|
-
return false;
|
794
|
-
}
|
795
|
-
}
|
796
|
-
if (ys == null) {
|
797
|
-
return false;
|
798
|
-
}
|
799
|
-
|
800
|
-
if (listLen(xs) !== listLen(ys)) {
|
801
|
-
return false;
|
802
|
-
}
|
803
|
-
|
804
|
-
if (xs.kind !== ys.kind) {
|
805
|
-
return false;
|
806
|
-
}
|
807
|
-
|
808
|
-
if (xs.kind === TernaryTreeKind.ternaryTreeLeaf && ys.kind === TernaryTreeKind.ternaryTreeLeaf) {
|
809
|
-
if (!dataEqual(xs.value, ys.value)) {
|
810
|
-
return false;
|
811
|
-
} else {
|
812
|
-
return true;
|
813
|
-
}
|
814
|
-
}
|
815
|
-
if (xs.kind === TernaryTreeKind.ternaryTreeBranch && ys.kind === TernaryTreeKind.ternaryTreeBranch) {
|
816
|
-
if (!sameListShape(xs.left, ys.left)) return false;
|
817
|
-
|
818
|
-
if (!sameListShape(xs.middle, ys.middle)) return false;
|
819
|
-
|
820
|
-
if (!sameListShape(xs.right, ys.right)) return false;
|
821
|
-
|
822
|
-
return true;
|
823
|
-
}
|
824
|
-
|
825
|
-
return false;
|
826
|
-
}
|
827
|
-
|
828
|
-
export function listEqual<T>(xs: TernaryTreeList<T>, ys: TernaryTreeList<T>): boolean {
|
829
|
-
if (xs === ys) {
|
830
|
-
return true;
|
831
|
-
}
|
832
|
-
if (listLen(xs) !== listLen(ys)) {
|
833
|
-
return false;
|
834
|
-
}
|
835
|
-
|
836
|
-
for (let idx = 0; idx < listLen(xs); idx++) {
|
837
|
-
if (!dataEqual(listGet(xs, idx), listGet(ys, idx))) {
|
838
|
-
return false;
|
839
|
-
}
|
840
|
-
}
|
841
|
-
|
842
|
-
return true;
|
843
|
-
}
|
844
|
-
|
845
|
-
export function checkListStructure<T>(tree: TernaryTreeList<T>): boolean {
|
846
|
-
if (tree == null) {
|
847
|
-
return true;
|
848
|
-
} else {
|
849
|
-
switch (tree.kind) {
|
850
|
-
case TernaryTreeKind.ternaryTreeLeaf:
|
851
|
-
if (tree.size !== 1) {
|
852
|
-
throw new Error(`Bad size at node ${formatListInline(tree)}`);
|
853
|
-
}
|
854
|
-
break;
|
855
|
-
case TernaryTreeKind.ternaryTreeBranch: {
|
856
|
-
if (tree.size !== listLen(tree.left) + listLen(tree.middle) + listLen(tree.right)) {
|
857
|
-
throw new Error(`Bad size at branch ${formatListInline(tree)}`);
|
858
|
-
}
|
859
|
-
|
860
|
-
if (tree.depth !== decideParentDepth(tree.left, tree.middle, tree.right)) {
|
861
|
-
let x = decideParentDepth(tree.left, tree.middle, tree.right);
|
862
|
-
throw new Error(`Bad depth at branch ${formatListInline(tree)}`);
|
863
|
-
}
|
864
|
-
|
865
|
-
checkListStructure(tree.left);
|
866
|
-
checkListStructure(tree.middle);
|
867
|
-
checkListStructure(tree.right);
|
868
|
-
break;
|
869
|
-
}
|
870
|
-
}
|
871
|
-
|
872
|
-
return true;
|
873
|
-
}
|
874
|
-
}
|
875
|
-
|
876
|
-
// excludes value at endIdx, kept aligned with JS & Clojure
|
877
|
-
export function slice<T>(tree: TernaryTreeList<T>, startIdx: number, endIdx: number): TernaryTreeList<T> {
|
878
|
-
// echo "slice {tree.formatListInline}: {startIdx}..{endIdx}"
|
879
|
-
if (endIdx > listLen(tree)) {
|
880
|
-
throw new Error("Slice range too large {endIdx} for {tree}");
|
881
|
-
}
|
882
|
-
if (startIdx < 0) {
|
883
|
-
throw new Error("Slice range too small {startIdx} for {tree}");
|
884
|
-
}
|
885
|
-
if (startIdx > endIdx) {
|
886
|
-
throw new Error("Invalid slice range {startIdx}..{endIdx} for {tree}");
|
887
|
-
}
|
888
|
-
if (startIdx === endIdx) {
|
889
|
-
return { kind: TernaryTreeKind.ternaryTreeBranch, size: 0, depth: 0 } as TernaryTreeList<T>;
|
890
|
-
}
|
891
|
-
|
892
|
-
if (tree.kind === TernaryTreeKind.ternaryTreeLeaf)
|
893
|
-
if (startIdx === 0 && endIdx === 1) {
|
894
|
-
return tree;
|
895
|
-
} else {
|
896
|
-
throw new Error(`Invalid slice range for a leaf: ${startIdx} ${endIdx}`);
|
897
|
-
}
|
898
|
-
|
899
|
-
if (startIdx === 0 && endIdx === listLen(tree)) {
|
900
|
-
return tree;
|
901
|
-
}
|
902
|
-
|
903
|
-
let leftSize = listLen(tree.left);
|
904
|
-
let middleSize = listLen(tree.middle);
|
905
|
-
let rightSize = listLen(tree.right);
|
906
|
-
|
907
|
-
// echo "sizes: {leftSize} {middleSize} {rightSize}"
|
908
|
-
|
909
|
-
if (startIdx >= leftSize + middleSize) {
|
910
|
-
return slice(tree.right, startIdx - leftSize - middleSize, endIdx - leftSize - middleSize);
|
911
|
-
}
|
912
|
-
if (startIdx >= leftSize)
|
913
|
-
if (endIdx <= leftSize + middleSize) {
|
914
|
-
return slice(tree.middle, startIdx - leftSize, endIdx - leftSize);
|
915
|
-
} else {
|
916
|
-
let middleCut = slice(tree.middle, startIdx - leftSize, middleSize);
|
917
|
-
let rightCut = slice(tree.right, 0, endIdx - leftSize - middleSize);
|
918
|
-
return concat(middleCut, rightCut);
|
919
|
-
}
|
920
|
-
|
921
|
-
if (endIdx <= leftSize) {
|
922
|
-
return slice(tree.left, startIdx, endIdx);
|
923
|
-
}
|
924
|
-
|
925
|
-
if (endIdx <= leftSize + middleSize) {
|
926
|
-
let leftCut = slice(tree.left, startIdx, leftSize);
|
927
|
-
let middleCut = slice(tree.middle, 0, endIdx - leftSize);
|
928
|
-
return concat(leftCut, middleCut);
|
929
|
-
}
|
930
|
-
|
931
|
-
if (endIdx <= leftSize + middleSize + rightSize) {
|
932
|
-
let leftCut = slice(tree.left, startIdx, leftSize);
|
933
|
-
let rightCut = slice(tree.right, 0, endIdx - leftSize - middleSize);
|
934
|
-
return concat(concat(leftCut, tree.middle), rightCut);
|
935
|
-
}
|
936
|
-
throw new Error("Unknown");
|
937
|
-
}
|
938
|
-
|
939
|
-
export function reverse<T>(tree: TernaryTreeList<T>): TernaryTreeList<T> {
|
940
|
-
if (tree == null) {
|
941
|
-
return tree;
|
942
|
-
}
|
943
|
-
|
944
|
-
switch (tree.kind) {
|
945
|
-
case TernaryTreeKind.ternaryTreeLeaf:
|
946
|
-
return tree;
|
947
|
-
case TernaryTreeKind.ternaryTreeBranch: {
|
948
|
-
let result: TernaryTreeList<T> = {
|
949
|
-
kind: TernaryTreeKind.ternaryTreeBranch,
|
950
|
-
size: tree.size,
|
951
|
-
depth: tree.depth,
|
952
|
-
left: reverse(tree.right),
|
953
|
-
middle: reverse(tree.middle),
|
954
|
-
right: reverse(tree.left),
|
955
|
-
};
|
956
|
-
return result;
|
957
|
-
}
|
958
|
-
}
|
959
|
-
}
|
960
|
-
|
961
|
-
export function listMapValues<T, V>(tree: TernaryTreeList<T>, f: (x: T) => V): TernaryTreeList<V> {
|
962
|
-
if (tree == null) {
|
963
|
-
return tree;
|
964
|
-
}
|
965
|
-
|
966
|
-
switch (tree.kind) {
|
967
|
-
case TernaryTreeKind.ternaryTreeLeaf: {
|
968
|
-
let result: TernaryTreeList<V> = {
|
969
|
-
kind: TernaryTreeKind.ternaryTreeLeaf,
|
970
|
-
size: tree.size,
|
971
|
-
value: f(tree.value),
|
972
|
-
};
|
973
|
-
return result;
|
974
|
-
}
|
975
|
-
case TernaryTreeKind.ternaryTreeBranch: {
|
976
|
-
let result: TernaryTreeList<V> = {
|
977
|
-
kind: TernaryTreeKind.ternaryTreeBranch,
|
978
|
-
size: tree.size,
|
979
|
-
depth: tree.depth,
|
980
|
-
left: tree.left == null ? emptyBranch : listMapValues(tree.left, f),
|
981
|
-
middle: tree.middle == null ? emptyBranch : listMapValues(tree.middle, f),
|
982
|
-
right: tree.right == null ? emptyBranch : listMapValues(tree.right, f),
|
983
|
-
};
|
984
|
-
return result;
|
985
|
-
}
|
986
|
-
}
|
987
|
-
}
|