@calcit/ternary-tree 0.0.24 → 0.0.26
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/.yarn/install-state.gz +0 -0
- package/.yarnrc.yml +6 -0
- package/README.md +24 -4
- package/TESTING.md +155 -0
- package/lib/bench.d.mts +11 -0
- package/lib/bench.mjs +99 -0
- package/lib/benchmark.d.mts +1 -0
- package/lib/benchmark.mjs +67 -0
- package/lib/list.d.mts +1 -0
- package/lib/list.mjs +265 -188
- package/lib/map.mjs +223 -161
- package/lib/test-list-detailed-perf.d.mts +1 -0
- package/lib/test-list-detailed-perf.mjs +165 -0
- package/lib/test-list-perf.d.mts +1 -0
- package/lib/test-list-perf.mjs +153 -0
- package/lib/test-list.mjs +202 -203
- package/lib/test-map-perf.d.mts +1 -0
- package/lib/test-map-perf.mjs +70 -0
- package/lib/test-map.mjs +201 -208
- package/lib/test-utils.d.mts +9 -5
- package/lib/test-utils.mjs +131 -18
- package/lib/{main.mjs → test.mjs} +3 -0
- package/lib/types.d.mts +1 -0
- package/package.json +14 -5
- /package/lib/{main.d.mts → test.d.mts} +0 -0
package/lib/test-list.mjs
CHANGED
|
@@ -1,208 +1,207 @@
|
|
|
1
1
|
import { listToString, initTernaryTreeList, initTernaryTreeListFromRange, indexOf, findIndex, reverse, checkListStructure, slice, listToPairs, listToItems, formatListInline, sameListShape, assocBefore, concat, assocAfter, prepend, append, rest, butlast, first, assocList, dissocList, listGet, insert, initEmptyTernaryTreeList, last, listLen, forceListInplaceBalancing, listEqual, indexToItems, listMapValues, concat2, } from "./list.mjs";
|
|
2
|
-
import { test, check,
|
|
2
|
+
import { describe, test, check, checkEqual, checkArrayEqual } from "./test-utils.mjs";
|
|
3
3
|
export let runListTests = () => {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
check(first(data11) === 1);
|
|
23
|
-
check(last(data11) === 11);
|
|
24
|
-
// assoc
|
|
25
|
-
let origin5 = [1, 2, 3, 4, 5];
|
|
26
|
-
let data5 = initTernaryTreeList(origin5);
|
|
27
|
-
let updated = assocList(data5, 3, 10);
|
|
28
|
-
check(listGet(updated, 3) === 10);
|
|
29
|
-
check(listGet(data5, 3) === 4);
|
|
30
|
-
check(listLen(updated) === listLen(data5));
|
|
31
|
-
for (let idx = 0; idx < listLen(data5); idx++) {
|
|
32
|
-
// echo data5.dissoc(idx).formatInline
|
|
33
|
-
check(listLen(dissocList(data5, idx)) === listLen(data5) - 1);
|
|
34
|
-
}
|
|
35
|
-
checkEqual(formatListInline(data5), "((1 2 _) 3 (4 5 _))");
|
|
36
|
-
checkEqual(formatListInline(dissocList(data5, 0)), "(2 3 (4 5 _))");
|
|
37
|
-
checkEqual(formatListInline(dissocList(data5, 1)), "(1 3 (4 5 _))");
|
|
38
|
-
checkEqual(formatListInline(dissocList(data5, 2)), "((1 2 _) (4 5 _) _)");
|
|
39
|
-
checkEqual(formatListInline(dissocList(data5, 3)), "((1 2 _) 3 5)");
|
|
40
|
-
checkEqual(formatListInline(dissocList(data5, 4)), "((1 2 _) 3 4)");
|
|
41
|
-
checkEqual(formatListInline(rest(initTernaryTreeList([1]))), "_");
|
|
42
|
-
checkEqual(formatListInline(rest(initTernaryTreeList([1, 2]))), "2");
|
|
43
|
-
checkEqual(formatListInline(rest(initTernaryTreeList([1, 2, 3]))), "(2 3 _)");
|
|
44
|
-
checkEqual(formatListInline(rest(initTernaryTreeList([1, 2, 3, 4]))), "((2 3 _) 4 _)");
|
|
45
|
-
checkEqual(formatListInline(rest(initTernaryTreeList([1, 2, 3, 4, 5]))), "(2 3 (4 5 _))");
|
|
46
|
-
checkEqual(formatListInline(butlast(initTernaryTreeList([1]))), "_");
|
|
47
|
-
checkEqual(formatListInline(butlast(initTernaryTreeList([1, 2]))), "1");
|
|
48
|
-
checkEqual(formatListInline(butlast(initTernaryTreeList([1, 2, 3]))), "(1 2 _)");
|
|
49
|
-
checkEqual(formatListInline(butlast(initTernaryTreeList([1, 2, 3, 4]))), "(1 (2 3 _) _)");
|
|
50
|
-
checkEqual(formatListInline(butlast(initTernaryTreeList([1, 2, 3, 4, 5]))), "((1 2 _) 3 4)");
|
|
51
|
-
});
|
|
52
|
-
test("list insertions", () => {
|
|
53
|
-
let origin5 = [1, 2, 3, 4, 5];
|
|
54
|
-
let data5 = initTernaryTreeList(origin5);
|
|
55
|
-
checkEqual(formatListInline(data5), "((1 2 _) 3 (4 5 _))");
|
|
56
|
-
checkEqual(formatListInline(insert(data5, 0, 10, false)), "(10 ((1 2 _) 3 (4 5 _)) _)");
|
|
57
|
-
checkEqual(formatListInline(insert(data5, 0, 10, true)), "((1 10 2) 3 (4 5 _))");
|
|
58
|
-
checkEqual(formatListInline(insert(data5, 1, 10, false)), "((1 10 2) 3 (4 5 _))");
|
|
59
|
-
checkEqual(formatListInline(insert(data5, 1, 10, true)), "((1 2 10) 3 (4 5 _))");
|
|
60
|
-
checkEqual(formatListInline(insert(data5, 2, 10, false)), "((1 2 _) (10 3 _) (4 5 _))");
|
|
61
|
-
checkEqual(formatListInline(insert(data5, 2, 10, true)), "((1 2 _) (3 10 _) (4 5 _))");
|
|
62
|
-
checkEqual(formatListInline(insert(data5, 3, 10, false)), "((1 2 _) 3 (10 4 5))");
|
|
63
|
-
checkEqual(formatListInline(insert(data5, 3, 10, true)), "((1 2 _) 3 (4 10 5))");
|
|
64
|
-
checkEqual(formatListInline(insert(data5, 4, 10, false)), "((1 2 _) 3 (4 10 5))");
|
|
65
|
-
checkEqual(formatListInline(insert(data5, 4, 10, true)), "(((1 2 _) 3 (4 5 _)) 10 _)");
|
|
66
|
-
let origin4 = [1, 2, 3, 4];
|
|
67
|
-
let data4 = initTernaryTreeList(origin4);
|
|
68
|
-
checkEqual(formatListInline(assocBefore(data4, 3, 10)), "(1 (2 3 _) (10 4 _))");
|
|
69
|
-
checkEqual(formatListInline(assocAfter(data4, 3, 10)), "(1 (2 3 _) (4 10 _))");
|
|
70
|
-
checkEqual(formatListInline(prepend(data4, 10)), "((10 1 _) (2 3 _) 4)");
|
|
71
|
-
checkEqual(formatListInline(append(data4, 10)), "(1 (2 3 _) (4 10 _))");
|
|
72
|
-
});
|
|
73
|
-
test("concat", () => {
|
|
74
|
-
let data1 = initTernaryTreeList([1, 2]);
|
|
75
|
-
let data2 = initTernaryTreeList([3, 4]);
|
|
76
|
-
let data3 = initTernaryTreeList([5, 6]);
|
|
77
|
-
let data4 = initTernaryTreeList([7, 8]);
|
|
78
|
-
check(formatListInline(concat(data1, data2)) === "(1 2 (3 4 _))");
|
|
79
|
-
check(formatListInline(concat(initTernaryTreeList([]), data1)) === "(1 2 _)");
|
|
80
|
-
check(formatListInline(concat(data1, data2, data3)) === "((1 2 _) (3 4 _) (5 6 _))");
|
|
81
|
-
check(formatListInline(concat(data1, data2, data3, data4)) === "((1 2 _) ((3 4 _) (5 6 _) _) (7 8 _))");
|
|
82
|
-
checkListStructure(concat(data1, data2));
|
|
83
|
-
checkListStructure(concat(data1, data2, data3));
|
|
84
|
-
checkListStructure(concat(data1, data2, data3, data4));
|
|
85
|
-
check(listLen(concat(data1, data2, data3, data4)) === 8);
|
|
86
|
-
});
|
|
87
|
-
test("check(equality", () => {
|
|
88
|
-
let origin4 = [1, 2, 3, 4];
|
|
89
|
-
let data4 = initTernaryTreeList(origin4);
|
|
90
|
-
let data4n = initTernaryTreeList(origin4);
|
|
91
|
-
let data4Made = prepend(initTernaryTreeList([2, 3, 4]), 1);
|
|
92
|
-
checkListStructure(data4);
|
|
93
|
-
checkListStructure(data4n);
|
|
94
|
-
checkListStructure(data4Made);
|
|
95
|
-
check(sameListShape(data4, data4) === true);
|
|
96
|
-
check(sameListShape(data4, data4n) === true);
|
|
97
|
-
check(sameListShape(data4, data4Made) === false);
|
|
98
|
-
check(listEqual(data4, data4n));
|
|
99
|
-
check(listEqual(data4, data4Made));
|
|
100
|
-
check(listEqual(data4n, data4Made));
|
|
101
|
-
check(data4 !== data4Made); // identical false
|
|
102
|
-
});
|
|
103
|
-
test("force balancing", () => {
|
|
104
|
-
var data = initTernaryTreeList([]);
|
|
105
|
-
for (let idx = 0; idx < 20; idx++) {
|
|
106
|
-
data = append(data, idx, true);
|
|
107
|
-
checkListStructure(data);
|
|
108
|
-
}
|
|
109
|
-
// echo data.formatInline
|
|
110
|
-
check(formatListInline(data) === "(((0 1 2) (3 4 5) (6 7 8)) ((9 10 11) (12 13 14) (15 16 17)) (18 19 _))");
|
|
111
|
-
forceListInplaceBalancing(data);
|
|
112
|
-
check(formatListInline(data) === "(((0 1 _) (2 3 4) (5 6 _)) ((7 8 _) (9 10 _) (11 12 _)) ((13 14 _) (15 16 17) (18 19 _)))");
|
|
113
|
-
// echo data.formatInline
|
|
114
|
-
});
|
|
115
|
-
test("iterator", () => {
|
|
116
|
-
let origin4 = [1, 2, 3, 4];
|
|
117
|
-
let data4 = initTernaryTreeList(origin4);
|
|
118
|
-
checkListStructure(data4);
|
|
119
|
-
var i = 0;
|
|
120
|
-
for (let item of listToItems(data4)) {
|
|
121
|
-
i = i + 1;
|
|
122
|
-
}
|
|
123
|
-
check(i === 4);
|
|
124
|
-
i = 0;
|
|
125
|
-
for (let [idx, item] of listToPairs(data4)) {
|
|
126
|
-
i = i + idx;
|
|
127
|
-
}
|
|
128
|
-
check(i === 6);
|
|
129
|
-
});
|
|
130
|
-
test("check structure", () => {
|
|
131
|
-
var data = initTernaryTreeList([]);
|
|
132
|
-
for (let idx = 0; idx < 20; idx++) {
|
|
133
|
-
data = append(data, idx, true);
|
|
134
|
-
checkListStructure(data);
|
|
135
|
-
}
|
|
136
|
-
check(checkListStructure(data));
|
|
137
|
-
for (let idx = 0; idx < 20; idx++) {
|
|
138
|
-
data = rest(data);
|
|
139
|
-
checkListStructure(data);
|
|
140
|
-
}
|
|
141
|
-
let origin11 = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11];
|
|
142
|
-
let data11 = initTernaryTreeList(origin11);
|
|
143
|
-
check(checkListStructure(data11));
|
|
144
|
-
checkListStructure(prepend(initEmptyTernaryTreeList(), 1));
|
|
145
|
-
checkListStructure(prepend(null, 1));
|
|
146
|
-
});
|
|
147
|
-
test("slices", () => {
|
|
148
|
-
var data = initTernaryTreeList([]);
|
|
149
|
-
for (let idx = 0; idx < 40; idx++) {
|
|
150
|
-
data = append(data, idx, true);
|
|
151
|
-
}
|
|
152
|
-
var list40 = [];
|
|
153
|
-
for (let idx = 0; idx < 40; idx++) {
|
|
154
|
-
list40.push(idx);
|
|
155
|
-
}
|
|
156
|
-
for (let i = 0; i < 40; i++) {
|
|
157
|
-
for (let j = i; j < 40; j++) {
|
|
158
|
-
check(arrayEqual([...listToItems(slice(data, i, j))], list40.slice(i, j)));
|
|
159
|
-
checkListStructure(slice(data, i, j));
|
|
4
|
+
describe("TernaryTreeList Tests", () => {
|
|
5
|
+
test("should initialize list correctly", () => {
|
|
6
|
+
check(listToString(initTernaryTreeList([1, 2, 3, 4])) === "TernaryTreeList[4, ...]");
|
|
7
|
+
let origin11 = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11];
|
|
8
|
+
let data11 = initTernaryTreeList(origin11);
|
|
9
|
+
check(checkListStructure(data11));
|
|
10
|
+
checkEqual(formatListInline(data11), "((1 (2 3 _) 4) (5 6 7) (8 (9 10 _) 11))");
|
|
11
|
+
checkArrayEqual([...listToItems(data11)], origin11);
|
|
12
|
+
checkArrayEqual([...listToItems(data11)], [...indexToItems(data11)]);
|
|
13
|
+
let emptyXs = new Array(0);
|
|
14
|
+
check(listEqual(initEmptyTernaryTreeList(), initTernaryTreeList(emptyXs)));
|
|
15
|
+
});
|
|
16
|
+
test("should perform basic list operations", () => {
|
|
17
|
+
let origin11 = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11];
|
|
18
|
+
let data11 = initTernaryTreeList(origin11);
|
|
19
|
+
// get
|
|
20
|
+
for (let idx = 0; idx < origin11.length; idx++) {
|
|
21
|
+
check(origin11[idx] === listGet(data11, idx));
|
|
160
22
|
}
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
23
|
+
check(first(data11) === 1);
|
|
24
|
+
check(last(data11) === 11);
|
|
25
|
+
// assoc
|
|
26
|
+
let origin5 = [1, 2, 3, 4, 5];
|
|
27
|
+
let data5 = initTernaryTreeList(origin5);
|
|
28
|
+
let updated = assocList(data5, 3, 10);
|
|
29
|
+
check(listGet(updated, 3) === 10);
|
|
30
|
+
check(listGet(data5, 3) === 4);
|
|
31
|
+
check(listLen(updated) === listLen(data5));
|
|
32
|
+
for (let idx = 0; idx < listLen(data5); idx++) {
|
|
33
|
+
check(listLen(dissocList(data5, idx)) === listLen(data5) - 1);
|
|
34
|
+
}
|
|
35
|
+
checkEqual(formatListInline(data5), "((1 2 _) 3 (4 5 _))");
|
|
36
|
+
checkEqual(formatListInline(dissocList(data5, 0)), "(2 3 (4 5 _))");
|
|
37
|
+
checkEqual(formatListInline(dissocList(data5, 1)), "(1 3 (4 5 _))");
|
|
38
|
+
checkEqual(formatListInline(dissocList(data5, 2)), "((1 2 _) (4 5 _) _)");
|
|
39
|
+
checkEqual(formatListInline(dissocList(data5, 3)), "((1 2 _) 3 5)");
|
|
40
|
+
checkEqual(formatListInline(dissocList(data5, 4)), "((1 2 _) 3 4)");
|
|
41
|
+
checkEqual(formatListInline(rest(initTernaryTreeList([1]))), "_");
|
|
42
|
+
checkEqual(formatListInline(rest(initTernaryTreeList([1, 2]))), "2");
|
|
43
|
+
checkEqual(formatListInline(rest(initTernaryTreeList([1, 2, 3]))), "(2 3 _)");
|
|
44
|
+
checkEqual(formatListInline(rest(initTernaryTreeList([1, 2, 3, 4]))), "((2 3 _) 4 _)");
|
|
45
|
+
checkEqual(formatListInline(rest(initTernaryTreeList([1, 2, 3, 4, 5]))), "(2 3 (4 5 _))");
|
|
46
|
+
checkEqual(formatListInline(butlast(initTernaryTreeList([1]))), "_");
|
|
47
|
+
checkEqual(formatListInline(butlast(initTernaryTreeList([1, 2]))), "1");
|
|
48
|
+
checkEqual(formatListInline(butlast(initTernaryTreeList([1, 2, 3]))), "(1 2 _)");
|
|
49
|
+
checkEqual(formatListInline(butlast(initTernaryTreeList([1, 2, 3, 4]))), "(1 (2 3 _) _)");
|
|
50
|
+
checkEqual(formatListInline(butlast(initTernaryTreeList([1, 2, 3, 4, 5]))), "((1 2 _) 3 4)");
|
|
51
|
+
});
|
|
52
|
+
test("should handle list insertions", () => {
|
|
53
|
+
let origin5 = [1, 2, 3, 4, 5];
|
|
54
|
+
let data5 = initTernaryTreeList(origin5);
|
|
55
|
+
checkEqual(formatListInline(data5), "((1 2 _) 3 (4 5 _))");
|
|
56
|
+
checkEqual(formatListInline(insert(data5, 0, 10, false)), "(10 ((1 2 _) 3 (4 5 _)) _)");
|
|
57
|
+
checkEqual(formatListInline(insert(data5, 0, 10, true)), "((1 10 2) 3 (4 5 _))");
|
|
58
|
+
checkEqual(formatListInline(insert(data5, 1, 10, false)), "((1 10 2) 3 (4 5 _))");
|
|
59
|
+
checkEqual(formatListInline(insert(data5, 1, 10, true)), "((1 2 10) 3 (4 5 _))");
|
|
60
|
+
checkEqual(formatListInline(insert(data5, 2, 10, false)), "((1 2 _) (10 3 _) (4 5 _))");
|
|
61
|
+
checkEqual(formatListInline(insert(data5, 2, 10, true)), "((1 2 _) (3 10 _) (4 5 _))");
|
|
62
|
+
checkEqual(formatListInline(insert(data5, 3, 10, false)), "((1 2 _) 3 (10 4 5))");
|
|
63
|
+
checkEqual(formatListInline(insert(data5, 3, 10, true)), "((1 2 _) 3 (4 10 5))");
|
|
64
|
+
checkEqual(formatListInline(insert(data5, 4, 10, false)), "((1 2 _) 3 (4 10 5))");
|
|
65
|
+
checkEqual(formatListInline(insert(data5, 4, 10, true)), "(((1 2 _) 3 (4 5 _)) 10 _)");
|
|
66
|
+
let origin4 = [1, 2, 3, 4];
|
|
67
|
+
let data4 = initTernaryTreeList(origin4);
|
|
68
|
+
checkEqual(formatListInline(assocBefore(data4, 3, 10)), "(1 (2 3 _) (10 4 _))");
|
|
69
|
+
checkEqual(formatListInline(assocAfter(data4, 3, 10)), "(1 (2 3 _) (4 10 _))");
|
|
70
|
+
checkEqual(formatListInline(prepend(data4, 10)), "((10 1 _) (2 3 _) 4)");
|
|
71
|
+
checkEqual(formatListInline(append(data4, 10)), "(1 (2 3 _) (4 10 _))");
|
|
72
|
+
});
|
|
73
|
+
test("should handle list concatenation", () => {
|
|
74
|
+
let data1 = initTernaryTreeList([1, 2]);
|
|
75
|
+
let data2 = initTernaryTreeList([3, 4]);
|
|
76
|
+
let data3 = initTernaryTreeList([5, 6]);
|
|
77
|
+
let data4 = initTernaryTreeList([7, 8]);
|
|
78
|
+
check(formatListInline(concat(data1, data2)) === "(1 2 (3 4 _))");
|
|
79
|
+
check(formatListInline(concat(initTernaryTreeList([]), data1)) === "(1 2 _)");
|
|
80
|
+
check(formatListInline(concat(data1, data2, data3)) === "((1 2 _) (3 4 _) (5 6 _))");
|
|
81
|
+
check(formatListInline(concat(data1, data2, data3, data4)) === "((1 2 _) ((3 4 _) (5 6 _) _) (7 8 _))");
|
|
82
|
+
check(checkListStructure(concat(data1, data2)));
|
|
83
|
+
check(checkListStructure(concat(data1, data2, data3)));
|
|
84
|
+
check(checkListStructure(concat(data1, data2, data3, data4)));
|
|
85
|
+
check(listLen(concat(data1, data2, data3, data4)) === 8);
|
|
86
|
+
});
|
|
87
|
+
test("should check equality correctly", () => {
|
|
88
|
+
let origin4 = [1, 2, 3, 4];
|
|
89
|
+
let data4 = initTernaryTreeList(origin4);
|
|
90
|
+
let data4n = initTernaryTreeList(origin4);
|
|
91
|
+
let data4Made = prepend(initTernaryTreeList([2, 3, 4]), 1);
|
|
92
|
+
check(checkListStructure(data4));
|
|
93
|
+
check(checkListStructure(data4n));
|
|
94
|
+
check(checkListStructure(data4Made));
|
|
95
|
+
check(sameListShape(data4, data4) === true);
|
|
96
|
+
check(sameListShape(data4, data4n) === true);
|
|
97
|
+
check(sameListShape(data4, data4Made) === false);
|
|
98
|
+
check(listEqual(data4, data4n));
|
|
99
|
+
check(listEqual(data4, data4Made));
|
|
100
|
+
check(listEqual(data4n, data4Made));
|
|
101
|
+
check(data4 !== data4Made); // identical false
|
|
102
|
+
});
|
|
103
|
+
test("should force balancing correctly", () => {
|
|
104
|
+
var data = initTernaryTreeList([]);
|
|
105
|
+
for (let idx = 0; idx < 20; idx++) {
|
|
106
|
+
data = append(data, idx, true);
|
|
107
|
+
check(checkListStructure(data));
|
|
108
|
+
}
|
|
109
|
+
check(formatListInline(data) === "(((0 1 2) (3 4 5) (6 7 8)) ((9 10 11) (12 13 14) (15 16 17)) (18 19 _))");
|
|
110
|
+
forceListInplaceBalancing(data);
|
|
111
|
+
check(formatListInline(data) === "(((0 1 _) (2 3 4) (5 6 _)) ((7 8 _) (9 10 _) (11 12 _)) ((13 14 _) (15 16 17) (18 19 _)))");
|
|
112
|
+
});
|
|
113
|
+
test("should handle iteration correctly", () => {
|
|
114
|
+
let origin4 = [1, 2, 3, 4];
|
|
115
|
+
let data4 = initTernaryTreeList(origin4);
|
|
116
|
+
check(checkListStructure(data4));
|
|
117
|
+
var count = 0;
|
|
118
|
+
for (let item of listToItems(data4)) {
|
|
119
|
+
count = count + 1;
|
|
120
|
+
}
|
|
121
|
+
check(count === 4);
|
|
122
|
+
var indexSum = 0;
|
|
123
|
+
for (let [idx, item] of listToPairs(data4)) {
|
|
124
|
+
indexSum = indexSum + idx;
|
|
125
|
+
}
|
|
126
|
+
check(indexSum === 6);
|
|
127
|
+
});
|
|
128
|
+
test("should maintain structure integrity", () => {
|
|
129
|
+
var data = initTernaryTreeList([]);
|
|
130
|
+
for (let idx = 0; idx < 20; idx++) {
|
|
131
|
+
data = append(data, idx, true);
|
|
132
|
+
check(checkListStructure(data));
|
|
133
|
+
}
|
|
134
|
+
check(checkListStructure(data));
|
|
135
|
+
for (let idx = 0; idx < 20; idx++) {
|
|
136
|
+
data = rest(data);
|
|
137
|
+
check(checkListStructure(data));
|
|
138
|
+
}
|
|
139
|
+
let origin11 = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11];
|
|
140
|
+
let data11 = initTernaryTreeList(origin11);
|
|
141
|
+
check(checkListStructure(data11));
|
|
142
|
+
check(checkListStructure(prepend(initEmptyTernaryTreeList(), 1)));
|
|
143
|
+
check(checkListStructure(prepend(null, 1)));
|
|
144
|
+
});
|
|
145
|
+
test("should handle slicing correctly", () => {
|
|
146
|
+
var data = initTernaryTreeList([]);
|
|
147
|
+
for (let idx = 0; idx < 40; idx++) {
|
|
148
|
+
data = append(data, idx, true);
|
|
149
|
+
}
|
|
150
|
+
var list40 = [];
|
|
151
|
+
for (let idx = 0; idx < 40; idx++) {
|
|
152
|
+
list40.push(idx);
|
|
153
|
+
}
|
|
154
|
+
for (let i = 0; i < 40; i++) {
|
|
155
|
+
for (let j = i; j < 40; j++) {
|
|
156
|
+
checkArrayEqual([...listToItems(slice(data, i, j))], list40.slice(i, j));
|
|
157
|
+
check(checkListStructure(slice(data, i, j)));
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
});
|
|
161
|
+
test("should reverse lists correctly", () => {
|
|
162
|
+
let data = initTernaryTreeList([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);
|
|
163
|
+
let reversedData = reverse(data);
|
|
164
|
+
checkArrayEqual([...listToItems(reversedData)], [...listToItems(data)].reverse());
|
|
165
|
+
check(checkListStructure(reversedData));
|
|
166
|
+
});
|
|
167
|
+
test("should traverse lists correctly", () => {
|
|
168
|
+
var count = 0;
|
|
169
|
+
let data = initTernaryTreeList([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);
|
|
170
|
+
check(checkListStructure(data));
|
|
171
|
+
for (let x of listToItems(data)) {
|
|
172
|
+
count = count + 1;
|
|
173
|
+
}
|
|
174
|
+
check(count === 10);
|
|
175
|
+
});
|
|
176
|
+
test("should find index correctly", () => {
|
|
177
|
+
let data = initTernaryTreeList([1, 2, 3, 4, 5, 6, 7, 8]);
|
|
178
|
+
check(indexOf(data, 2) === 1);
|
|
179
|
+
check(findIndex(data, (x) => x === 2) === 1);
|
|
180
|
+
check(indexOf(data, 9) === -1);
|
|
181
|
+
check(findIndex(data, (x) => x === 9) === -1);
|
|
182
|
+
});
|
|
183
|
+
test("should map values correctly", () => {
|
|
184
|
+
let data = initTernaryTreeList([1, 2, 3, 4]);
|
|
185
|
+
let data2 = initTernaryTreeList([1, 4, 9, 16]);
|
|
186
|
+
let data3 = listMapValues(data, (x) => x * x);
|
|
187
|
+
check(checkListStructure(data3));
|
|
188
|
+
check(listEqual(data2, data3));
|
|
189
|
+
check(formatListInline(data2) === formatListInline(data3));
|
|
190
|
+
});
|
|
191
|
+
test("should handle range initialization", () => {
|
|
192
|
+
let data1 = initTernaryTreeList([3, 4]);
|
|
193
|
+
let data2 = initTernaryTreeListFromRange([1, 2, 3, 4, 5, 6], 2, 4);
|
|
194
|
+
check(listEqual(data1, data2));
|
|
195
|
+
check(checkListStructure(data1));
|
|
196
|
+
check(checkListStructure(data2));
|
|
197
|
+
});
|
|
198
|
+
test("should handle concat loop stress test", () => {
|
|
199
|
+
let data1 = initTernaryTreeList([3, 4]);
|
|
200
|
+
let data2 = initTernaryTreeList([5]);
|
|
201
|
+
for (let i = 0; i < 100; i++) {
|
|
202
|
+
data1 = concat2(data1, data2);
|
|
203
|
+
}
|
|
204
|
+
console.log("concat into depth", formatListInline(data1));
|
|
205
|
+
});
|
|
207
206
|
});
|
|
208
207
|
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function runPerformanceTests(): void;
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { initTernaryTreeMap, initTernaryTreeMapFromArray, assocMap, contains, mapGetDefault, dissocMap, toPairsArray, initEmptyTernaryTreeMap, } from "./map.mjs";
|
|
2
|
+
function createTestData(size) {
|
|
3
|
+
const data = [];
|
|
4
|
+
for (let i = 0; i < size; i++) {
|
|
5
|
+
data.push([i, `value_${i}`]);
|
|
6
|
+
}
|
|
7
|
+
return data;
|
|
8
|
+
}
|
|
9
|
+
function measureTime(name, fn) {
|
|
10
|
+
const start = performance.now();
|
|
11
|
+
const result = fn();
|
|
12
|
+
const end = performance.now();
|
|
13
|
+
console.log(`${name}: ${(end - start).toFixed(2)}ms`);
|
|
14
|
+
return result;
|
|
15
|
+
}
|
|
16
|
+
export function runPerformanceTests() {
|
|
17
|
+
console.log("\n=== Performance Tests ===");
|
|
18
|
+
const sizes = [100, 1000, 5000, 10000];
|
|
19
|
+
for (const size of sizes) {
|
|
20
|
+
console.log(`\n--- Testing with ${size} elements ---`);
|
|
21
|
+
const testData = createTestData(size);
|
|
22
|
+
const mapData = new Map(testData);
|
|
23
|
+
// Test initTernaryTreeMapFromArray
|
|
24
|
+
const treeFromArray = measureTime(`initTernaryTreeMapFromArray(${size})`, () => {
|
|
25
|
+
return initTernaryTreeMapFromArray(testData);
|
|
26
|
+
});
|
|
27
|
+
// Test initTernaryTreeMap
|
|
28
|
+
const treeFromMap = measureTime(`initTernaryTreeMap(${size})`, () => {
|
|
29
|
+
return initTernaryTreeMap(mapData);
|
|
30
|
+
});
|
|
31
|
+
// Test sequential assoc operations
|
|
32
|
+
measureTime(`Sequential assoc(${size})`, () => {
|
|
33
|
+
let tree = initEmptyTernaryTreeMap();
|
|
34
|
+
for (const [k, v] of testData) {
|
|
35
|
+
tree = assocMap(tree, k, v);
|
|
36
|
+
}
|
|
37
|
+
return tree;
|
|
38
|
+
});
|
|
39
|
+
// Test lookups
|
|
40
|
+
const lookupKeys = testData.slice(0, Math.min(100, size)).map(([k]) => k);
|
|
41
|
+
measureTime(`Lookups(${lookupKeys.length})`, () => {
|
|
42
|
+
for (const key of lookupKeys) {
|
|
43
|
+
contains(treeFromArray, key);
|
|
44
|
+
mapGetDefault(treeFromArray, key, "default");
|
|
45
|
+
}
|
|
46
|
+
});
|
|
47
|
+
// Test dissoc operations
|
|
48
|
+
const dissocKeys = testData.slice(0, Math.min(50, size)).map(([k]) => k);
|
|
49
|
+
measureTime(`Dissoc(${dissocKeys.length})`, () => {
|
|
50
|
+
let tree = treeFromArray;
|
|
51
|
+
for (const key of dissocKeys) {
|
|
52
|
+
tree = dissocMap(tree, key);
|
|
53
|
+
}
|
|
54
|
+
return tree;
|
|
55
|
+
});
|
|
56
|
+
// Test toPairsArray
|
|
57
|
+
measureTime(`toPairsArray(${size})`, () => {
|
|
58
|
+
return toPairsArray(treeFromArray);
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
console.log("\n=== Memory usage test ===");
|
|
62
|
+
const largeData = createTestData(50000);
|
|
63
|
+
console.log(`Testing with ${largeData.length} elements for memory efficiency`);
|
|
64
|
+
measureTime("Large dataset creation", () => {
|
|
65
|
+
return initTernaryTreeMapFromArray(largeData);
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
if (import.meta.url === `file://${process.argv[1]}`) {
|
|
69
|
+
runPerformanceTests();
|
|
70
|
+
}
|