Here is an approach that's uses a nice feature of modern JS. Generators..
Using generators you can create composable code. Instead of creating 1 function that does this one specific thing, you can compose a function than stream together multiple generators. This is great for making re-usable code.
Below I've created 3 function,.
- randomValues => this just generates random number between a range.
- repeatLimit => this generator just prevents x amount of repeated values
- iterCount => this generator stop after count iterations
All you do then is compose all these generators together, but the bonus is that these generators can be used in other places. eg. [...repeatLimit(3, [1,1,1,1, 0,0,0,0])]
would return 1,1,1,0,0,0
.
function* randValues(min, max) {
const range = max - min;
while (true)
yield min + Math.trunc(Math.random() * range);
}
function* repeatLimit(limit, gen) {
let rcount = 0, rvalue;
for (let g of gen) {
if (rvalue === g) rcount += 1; else rcount = 1;
rvalue = g;
if (rcount <= limit) yield g;
}
}
function* iterCount(count, gen) {
for (let g of gen) {
yield g;
count --;
if (count <= 0) break;
}
}
const gen =
iterCount(22, repeatLimit(3, randValues(0, 2)));
for (const r of gen) {
console.log(r);
}