for example:
const arrayOfLists = ['fox', 'ant', 'bird', 'lion', 'wolf', 'deer', 'bear', 'frog', 'hen', 'mole', 'duck', 'goat', 'dog', 'cat', 'bat', 'rooster', 'cow'];
function find(word) {
"I'm not sure about this part"
}
const result = find('dgocat')
console.log(result)
it should return me ['goat', 'dog', 'cat']
in the console
CodePudding user response:
The strategy strictly depends on the criteria chosen to determine how a word should match the allowed words in the array.
Now given the requirements like:
'dgocat'
should match ['goat', 'dog', 'cat']
It seems to me a good criteria is: if the input word contains all the letters contained in a word in the list, the target will match.
This is achieved with the functions countLetters(word)
and compareLettersCount(word, allowedWord)
that respectively do count the letters in a word and compare that results coming from two different words.
The comparison works checking if for each letter in the allowed word the letter count of the input word for that letter is equal or greater (also greater because the input word may contain several times the same letter like dogg
but it still should match with dog
).
const arrayOfLists = ['fox', 'ant', 'bird', 'lion', 'wolf', 'deer', 'bear', 'frog', 'hen', 'mole', 'duck', 'goat', 'dog', 'cat', 'bat', 'rooster', 'cow'];
/**
* Returns an array with the allowed words that the input word tried to target
*/
function find(word) {
const matchingWords = [];
//for each word in arrayOfLists
for(let i=0;i<arrayOfLists.length;i ){
//current allowed word
const allowedWord = arrayOfLists[i];
//gets the letters count for the input word
const lettersCountWord = countLetters(word);
//gets the letters count for the allowed word
const lettersCountAllowedWord = countLetters(allowedWord);
//if the input word has the same letters count (or greater) for the letters in allowedWord
if ( compareLettersCount(lettersCountWord, lettersCountAllowedWord) ){
//push this allowedWord in the returning array
matchingWords.push(allowedWord)
//break;
}
}
return matchingWords;
}
/**
* Returns an object with the count of each letter in word
*/
function countLetters(word){
const r = {};
[...word].forEach(letter => {
if(!r[letter])
r[letter] = 1;
else
r[letter] ;
});
return r;
}
/**
* Compares the letterCount returned from word and allowedWord
* return true if word contains the same counters (or greater) for the letters in allowedWord
* otherwise returns false
*/
function compareLettersCount(word, allowedWord){
for(let letter in allowedWord){
if(word[letter] === undefined || word[letter] < allowedWord[letter])
return false;
}
return true;
}
const result = find('dgocat')
console.log(result)
CodePudding user response:
A other way is to use the levenshtein algorithm. Here is a wiki. It calculates the minimum number of single-character edits (insertions, deletions or substitutions).
function levenshtein() {
function _min(d0, d1, d2, bx, ay) {
return d0 < d1 || d2 < d1
? d0 > d2
? d2 1
: d0 1
: bx === ay
? d1
: d1 1;
}
return function (a, b) {
if (a === b) {
return 0;
}
if (a.length > b.length) {
var tmp = a;
a = b;
b = tmp;
}
var la = a.length;
var lb = b.length;
while (la > 0 && a.charCodeAt(la - 1) === b.charCodeAt(lb - 1)) {
la--;
lb--;
}
var offset = 0;
while (offset < la && a.charCodeAt(offset) === b.charCodeAt(offset)) {
offset ;
}
la -= offset;
lb -= offset;
if (la === 0 || lb < 3) {
return lb;
}
var x = 0;
var y;
var d0;
var d1;
var d2;
var d3;
var dd;
var dy;
var ay;
var bx0;
var bx1;
var bx2;
var bx3;
var vector = [];
for (y = 0; y < la; y ) {
vector.push(y 1);
vector.push(a.charCodeAt(offset y));
}
var len = vector.length - 1;
for (; x < lb - 3; ) {
bx0 = b.charCodeAt(offset (d0 = x));
bx1 = b.charCodeAt(offset (d1 = x 1));
bx2 = b.charCodeAt(offset (d2 = x 2));
bx3 = b.charCodeAt(offset (d3 = x 3));
dd = x = 4;
for (y = 0; y < len; y = 2) {
dy = vector[y];
ay = vector[y 1];
d0 = _min(dy, d0, d1, bx0, ay);
d1 = _min(d0, d1, d2, bx1, ay);
d2 = _min(d1, d2, d3, bx2, ay);
dd = _min(d2, d3, dd, bx3, ay);
vector[y] = dd;
d3 = d2;
d2 = d1;
d1 = d0;
d0 = dy;
}
}
for (; x < lb; ) {
bx0 = b.charCodeAt(offset (d0 = x));
dd = x;
for (y = 0; y < len; y = 2) {
dy = vector[y];
vector[y] = dd = _min(dy, d0, dd, bx0, vector[y 1]);
d0 = dy;
}
}
return dd;
};
}
To use it:
function findWord(word) {
arrayOfLists.filter(f => levenshtein()(word, f) <= 3)
}
The number 3 means it need 3 steps to until both words agree. Sample: 1: delete one letter, 2: add one letter,... and so on. With this number you can play and fine tune your function.
Here is a Stackblitz.
CodePudding user response:
You can use simple logic:
- Loop on
arrayOfLists
- For every word, split and check if every character is in password word.
- Return list of matching word
const arrayOfLists = ['fox', 'ant', 'bird', 'lion', 'wolf', 'deer', 'bear', 'frog', 'hen', 'mole', 'duck', 'goat', 'dog', 'cat', 'bat', 'rooster', 'cow'];
function find(word) {
return arrayOfLists.filter(
(str) => [...str].every(
(char) => word.includes(char)
)
)
}
const result = find('dgocat')
console.log(result)