Skip to content

Commit a13d14e

Browse files
committed
Improve ids function reusing smaller ids to construct large ones
Fixes: #5
1 parent 0222be2 commit a13d14e

File tree

1 file changed

+78
-14
lines changed

1 file changed

+78
-14
lines changed

Exercises/1-ids.js

+78-14
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,84 @@
11
'use strict';
22

3-
const ids = function* () {
4-
const free = ['0'];
5-
const prepared = { has: false, value: '' };
6-
7-
while (true) {
8-
if (prepared.has) {
9-
prepared.has = false;
10-
yield prepared.value;
3+
const allCombinations = function* (arrs) {
4+
const ixs = new Array(arrs.length).fill(0);
5+
const combination = arrs.map(arr => arr[0]);
6+
7+
const incIx = i => {
8+
ixs[i]++;
9+
combination[i] = arrs[i][ixs[i]];
10+
};
11+
12+
const resetIx = i => {
13+
ixs[i] = 0;
14+
combination[i] = arrs[i][ixs[i]];
15+
};
16+
17+
while (ixs[0] < arrs[0].length) {
18+
yield combination.join('');
19+
20+
let i = ixs.length - 1;
21+
incIx(i);
22+
23+
while (i > 0 && ixs[i] === arrs[i].length) {
24+
incIx(i - 1);
25+
resetIx(i);
26+
i--;
27+
}
28+
}
29+
};
30+
31+
const greedySizes = (totalSize, sizesInCache) => {
32+
const sizes = [];
33+
let i = sizesInCache.length - 1;
34+
while (totalSize > 0) {
35+
while (sizesInCache[i] > totalSize) {
36+
i--;
37+
}
38+
39+
while (totalSize >= sizesInCache[i]) {
40+
totalSize -= sizesInCache[i];
41+
sizes.push(sizesInCache[i]);
42+
}
43+
}
44+
return sizes;
45+
};
46+
47+
const mapGen = function* (g, f) {
48+
for (const el of g) {
49+
yield f(el);
50+
}
51+
};
52+
53+
const prependOne = s => '1' + s;
54+
55+
const ids = function* (maxSizeInCache = 20, cache = {}) {
56+
if (!(1 in cache)) {
57+
cache[1] = ['00', '10'];
58+
}
59+
60+
let sizesInCache = Object.keys(cache).sort();
61+
for (let size = 1; ; size++) {
62+
if (size in cache) {
63+
yield* mapGen(cache[size], prependOne);
64+
continue;
65+
}
66+
67+
const combinationGroups = greedySizes(size, sizesInCache)
68+
.map(size => cache[size]);
69+
const combinations = allCombinations(combinationGroups);
70+
71+
if (size > maxSizeInCache) {
72+
yield* mapGen(combinations, prependOne);
73+
continue;
74+
}
75+
76+
cache[size] = [];
77+
for (const combination of combinations) {
78+
cache[size].push(combination);
79+
yield prependOne(combination);
1180
}
12-
const nextFree = free.shift();
13-
free.push('01' + nextFree);
14-
free.push('00' + nextFree);
15-
prepared.value = '11' + nextFree;
16-
prepared.has = true;
17-
yield '10' + nextFree;
81+
sizesInCache = Object.keys(cache).sort();
1882
}
1983
};
2084

0 commit comments

Comments
 (0)