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 ) ); }