Given 3 characters (abc), I want to generate all possible 5-letter strings with them (aaaaa, aaaab, … ccccb, ccccc)
const s = 'byg';
const p = [];
for (let i = 0; i < 3; i++) {
for (let j = 0; j < 3; j++) {
for (let k = 0; k < 3; k++) {
for (let l = 0; l < 3; l++) {
for (let m = 0; m < 3; m++) {
p.push(s[i] + s[j] + s[k] + s[l] + s[m]);
}
}
}
}
}
console.log(p, p.length === 3 ** 5)This feels like an inefficient way to do this, so is there a more elegant/efficient way to do this?
Advertisement
Answer
Your nested for loops does imply that code can be refactored either using recursion or as in my example below by creating a higher level loop.
This approach allows us to generate strings of any desired length.
let characters = "abc";
let desiredLength = 5;
let theSet = [""];
for ( let length = 0; length < desiredLength; length++){
let extendedSet = [];
theSet.forEach( (item) =>
extendedSet.push( ...extendWith( item, characters) )
)
theSet = extendedSet;
}
console.log('result ', theSet);
// given a strings and a set of characters
// generate an array of string extended with each
// of the characters.
// "a" with "xy" generates
// [ "ax", "ay" ]
function extendWith( extendThis, characters){
let result = [];
[...characters].forEach( (c) => result.push(extendThis+c) );
return result;
}
We can make that extendWith function more succinct like this
function extendWith( extendThis, characters){
return [...characters].map( c => extendThis + c );
}
and as it’s now just a one line expression we can dispense with the utility function and simplify a bit more
for ( let length = 0; length < desiredLength; length++){
theSet = theSet.flatMap( (item) =>
[...characters].map( c => item + c )
);
}