The code should generate all variations of a word that have letters in parentheses. Currently, it works when there are multiple letters in the parentheses, but not when there is only one letter inside.
Example:
t(ea)st
test, tast
Here, "test" and "tast" are generated from the word "t(ea)st". That works fine.
But what doesn’t work is when there is only one letter in the parentheses.
Example:
t(e)st
test
Only the word "test" is generated, but it should also generate "tst".
The problem now is that no matter what I try, I can’t get it to generate the word "tst".
If there are multiple parentheses with only one letter inside, as in this example:
t(e)st(s) – then the following words should be generated:
tests, test, tsts, tst
const generateVariations = (() => {
const cache = {};
return (word) => {
if (cache[word]) {
return cache[word];
}
const variations = [];
// Find all groups of letters in parentheses
const groups = word.match(/(([^)]+))/g) || [];
// Create an array of arrays, where each subarray contains the letters in a group
const letterArrays = groups.map(group => group.slice(1, -1).split(''));
// If a group has only one letter, remove the parentheses and add the letter to the list of groups
const modifiedGroups = groups.reduce((acc, group) => {
if (group.length === 3) {
acc.push(group[1]);
} else {
acc.push(group);
}
return acc;
}, []);
// Generate all possible combinations of letters from each group
const combinations = cartesianProduct(...letterArrays);
// Generate variations by replacing each group with each combination of letters from that group
for (const combination of combinations) {
let newWord = word;
for (let i = 0; i < modifiedGroups.length; i++) {
const group = modifiedGroups[i];
if (group.length === 1) {
newWord = newWord.replace(`(${group})`, group);
} else {
newWord = newWord.replace(groups[i], combination[i]);
}
}
variations.push(newWord);
}
cache[word] = variations;
return variations;
};
})();
function cartesianProduct(...arrays) {
let result = [[]];
for (const array of arrays) {
const newResult = [];
for (const x of result) {
for (const y of array) {
newResult.push([...x, y]);
}
}
result = newResult;
}
return result;
}
2
Answers
You already have a function for cartesian products, all what’s left is to parse your input into an array of arrays, for example:
Then simply apply
cartesianProduct(...arrays)
and join each result.Expand and merge, by splitting each
(...)
pattern, with a check to see how many letters are in that pattern. If it’s more than one, regular split. If it’s only one, don’t split but just create the array of letters yourself, since you know it needs to be["", thatOneLetter]
.And of course, bonus points for rewriting that as a breadth-first expansion so you can use a single function call with a while loop that uses an "strings left to expand" array in addition to
results
, instead of the much more expensive recursive approach. But that’s an exercise for the reader.