问题:
I have a string that I'd like to get all possible replace-ment combinations on using the following substitutions:
var equiv = {
"a": "4",
"b": "8",
"e": "3",
"i":...
可以将文章内容翻译成中文,广告屏蔽插件会导致该功能失效:
问题:
I have a string that I'd like to get all possible replace
-ment combinations on using the following substitutions:
var equiv = {
"a": "4",
"b": "8",
"e": "3",
"i": "1",
"l": "1",
"o": "0",
"t": "7"
}
I would like to define a String.prototype
function, something like:
String.prototype.l33tCombonations = function()
{
var toReturn = [];
for (var i in equiv)
{
// this.???
// toReturn.push(this???)
}
return toReturn;
}
So I could feed in something like "tomato".l33tCombinations()
and get back:
["tomato", "t0mato", "t0mat0", "tomat0", "toma7o", "t0ma7o", "t0m470", ...].
Order is not important. Thoughts?
回答1:
I would use a recursive approach, that traverses the string char by char:
const toL33t = { "a": "4", "b": "8", "e": "3", "i": "1", "l": "1", "o": "0", "t": "7" };
function* l33t(string, previous = "") {
const char = string[0];
// Base case: no chars left, yield previous combinations
if(!char) {
yield previous;
return;
}
// Recursive case: Char does not get l33t3d
yield* l33t(string.slice(1), previous + char);
// Recursive case: Char gets l33t3d
if(toL33t[char])
yield* l33t(string.slice(1), previous + toL33t[char]);
}
console.log(...l33t("tomato"));
If you really need it on the prototype thats also possibl3, but I wouldn't recommend that:
String.prototype.l33t = function() {
return [...l33t(this)];
};
console.log("stuff".l33t());
回答2:
You could take a cartesian product for generating the wanted values.
function leet(string) {
const
cartesian = (a, b) => a.reduce((r, v) => r.concat(b.map(w => [].concat(v, w))), []),
code = { a: "4", b: "8", e: "3", i: "1", l: "1", o: "0", t: "7" };
return Array
.from(string, c => c in code ? [c, code[c]] : [c])
.reduce(cartesian)
.map(a => a.join(''));
}
console.log(leet('tomatoe'));
.as-console-wrapper { max-height: 100% !important; top: 0; }
回答3:
You can do something like this using reduce
The idea is to loop through each character and add every combination to the accumulator. If you encounter a character which isn't part of equiv
, just add the character to every item in the accumulator. If the character does exist in equiv
, duplicate all the previous combinations and add another set of combinations with the equiv[<character>]
const equiv = {
"a": "4",
"b": "8",
"e": "3",
"i": "1",
"l": "1",
"o": "0",
"t": "7"
}
const input = "tomato";
const output = [...input].reduce((acc, c, i) => {
const r = equiv[c];
if (i === 0) {
return r ? [c, r] : [c];
}
const updated = acc.map(a => a + c);
const newItems = r ? acc.map(a => a + r) : [];
return [...updated, ...newItems]
}, [])
console.log(output)
回答4:
I have approached this in a recursive way, on each iteration of the recursion, a new character of the string is analyzed, if this character have a replacement, then both the character
and the replacement
are concatenated to all previous results making a new set of results, otherwise only the character
is concatenated to all the previous results. Note, I have abuse of the spread operator for this approach.
var equiv = {a: "4", b: "8", e: "3", i: "1", l: "1", o: "0", t: "7"};
const genComb = (str, arr) =>
{
if (!str) return arr; // Finish condition.
let c = str[0]; // New char to be appended.
let r = equiv[c]; // New char replacement.
return genComb(
str.slice(1),
[...arr.map(e => e + c), ...(r ? arr.map(e => e + r) : [])]
);
};
String.prototype.l33tCombinations = function()
{
return genComb(this, [""], 0);
}
console.log("tomato".l33tCombinations());
回答5:
I think this might yield the desired result! Loop through each letter and every time a new replacement is found, add a new word to toReturn
and make sure to search each new word!
var equiv = {
"a": "4",
"b": "8",
"e": "3",
"i": "1",
"l": "1",
"o": "0",
"t": "7"
}
String.prototype.l33tCombinations = function() {
var toReturn = [this.toLowerCase()];
for (let i = 0; i < toReturn.length; i++) {
for (let j = 0; j < toReturn[i].length; j++) {
if (equiv[toReturn[i][j]]) {
let newWord = toReturn[i].split('');
newWord[j] = equiv[newWord[j]];
let newWordJoined = newWord.join('');
if (!toReturn.includes(newWordJoined))
toReturn.push(newWordJoined);
}
}
}
return toReturn;
}
console.log('tomato'.l33tCombinations());