I have a really specific problem and can’t think of an answer.
I have a function to generate a letter H or V.
I want to make that if the generator exceedes the limit for H to pick V and if the limit for V gets exceeded to pick H.
Example
Limit for H is 10 Limit for V is 10
function generateLetter(){
let result = randomLetter; // Just pseudocode it picks H or V
if The limit for H is exceeded to pick
}
the result would be the letter H 10 times and letter V 10 times.
This is my code
H5 = Limit for H number V5 = Limit for V number
function generateType(h5, v5){
let type = ["H", "V"];
let randomType = Math.round(Math.random());
let selectedType = type[randomType];
if(totalH < h5 && selectedType == "H"){
totalH += 1;
}
if(totalV < v5 && selectedType == "V"){
totalV += 1;
}
if(totalH >= h5 && totalV < v5){
selectedType = "V";
}
if(totalV >= v5 && totalH < h5){
selectedType = "H";
}
return selectedType;
}
EDIT
I have a for loop that loops like 20 times
let text = [];
for(let i = 0; i < 20; i++){
text1 = generateType();
text.push(text1);
}
I want to make it so that there is exactly 10 H and 10 V or any number i choose
This is the entire Code
worker.js Using Web Workers
let letters = ["a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q","r", "s", "t", "u", "v", "w", "x", "y", "z"];
let tags = [];
let items = [];
let index = 0;
let textBack = "";
var hA = 0;
var vA = 0;
var minA;
var maxA;
let totalH = 0;
let totalV = 0;
function saveDATA(min, max, h, v){
minA = min;
maxA = max;
hA = Math.round(h / 50);
vA = Math.round(v / 50);
}
function generateTags(totalTags){
let tag;
for(let i = 0; i < totalTags; i++){
let r1 = Math.ceil(Math.random() * 15);
let r2 = Math.ceil(Math.random() * 7);
let r3 = Math.ceil(Math.random() * 5);
let r4 = Math.ceil(Math.random() * 9);
let r5 = Math.ceil(Math.random() * 17);
// console.log(r1, r2, r3, r4, r5);
tag = letters[r1] + letters[r2] + letters[r3] + letters[r4] + letters[r5];
if(tags.includes(tag)){
// Do nothing
let random = Math.round(Math.random());
if(random == 1){
tags.push(tag);
tags.concat(tag);
}
} else{
tags.push(tag);
tags.concat(tag);
tags.push(tag);
tags.concat(tag);
items.push(tag);
}
if(totalTags < 2){
return tag;
}
}
}
function generateType(h5, v5){
let type = ["H", "V"];
let randomType = Math.round(Math.random());
let selectedType = type[randomType];
if(totalH < h5 && selectedType == "H"){
totalH += 1;
}
if(totalV < v5 && selectedType == "V"){
totalV += 1;
}
if(totalH >= h5 && totalV < v5){
selectedType = "V";
}
if(totalV >= v5 && totalH < h5){
selectedType = "H";
}
return selectedType;
}
function getRandomInt(min, max) {
let minB, maxB;
minB = Math.ceil(Number(min));
maxB = Math.floor(Number(max));
return Math.floor(Math.random() * (maxB - minB + 1)) + minB;
}
function generateTagsInsideItem(){
let totalTags = getRandomInt(minA, maxA);
return totalTags;
}
function generateTagsItem(h4, v4){
let totalTags = generateTagsInsideItem();
let tags = "";
for(let i = 0; i < totalTags; i++) {
tags += " " + generateTags(1);
}
let text = generateType(h4, v4) + " " + totalTags + " " + tags;
return text;
}
function generateDocumnet(id, items, horizontal, vertical) {
hA = Math.round(Number(horizontal) / 50);
vA = Math.round(Number(vertical) / 50);
let totalItems = items;
for(let i = 0; i < totalItems; i++){
textBack += "n" + generateTagsItem(hA, vA);
}
}
self.addEventListener("message", function(e) {
saveDATA(e.data.minimum, e.data.maximum, e.data.horizontal, e.data.vertical);
generateDocumnet(e.data.id, e.data.count, e.data.horizontal, e.data.vertical);
this.postMessage({id: e.data.id , result: textBack});
}, false);
Advertisement
Answer
Fill an array with 10 Hs, 10 Vs, then shuffle the array. Return consecutive elments from the array. Wrap everything in a closure, so that you do not pollute global state and can create differently parametrized “sequences”:
function shuffle(array) {
for (let i = array.length - 1; i > 0; --i) {
const j = Math.floor(Math.random() * (i + 1));
[array[i], array[j]] = [array[j], array[i]];
}
}
function generate(hs, vs) {
var a = new Array(hs + vs)
.fill('H', 0, hs)
.fill('V', hs, hs + vs);
shuffle(a);
var i = 0;
return () => a[i++];
}
let sequence = generate(4, 2);
for (let i = 0; i < 8; ++i) {
console.log(sequence());
}
sequence = generate(2, 4);
for (let i = 0; i < 8; ++i) {
console.log(sequence());
}
If you always need the same number of H’s and V’s, you could simply keep a single array and shuffle it each time before iterating (shuffling is O(n) and requires only 20 steps for 20 elements). This would avoid having to “generate” a new sequence every time.
Or you could split the “generator” and the “iterator” part, making it easy for you to reuse arrays and iterate a given sequence multiple times:
function shuffle(array) {
for (let i = array.length - 1; i > 0; --i) {
const j = Math.floor(Math.random() * (i + 1));
[array[i], array[j]] = [array[j], array[i]];
}
}
function generate(hs, vs) {
var a = new Array(hs + vs)
.fill('H', 0, hs)
.fill('V', hs, hs + vs);
shuffle(a);
return a;
}
function iterate(a) {
var i = 0;
return () => a[i++];
}
let array = generate(4, 2)
let sequence = iterate(array);
for (let i = 0; i < 8; ++i) {
console.log(sequence());
}
// iterate again from the beginning
sequence = iterate(array);
for (let i = 0; i < 8; ++i) {
console.log(sequence());
}