Mutations using regex, passing all tests but one

Tell us what’s happening:

I’m using Regex to solve this challenge and I pass all tests but:

mutation([“hello”, “Hello”]) should return true.

What do you suppose the issue could be? I’ve already added “i” so it isnt case sensitive. Thanks for your help. :sweat_smile:

Your code so far


function mutation(arr) {
  let patt = new RegExp(/[arr.1]/ig);
  return patt.test(arr[0]);
}

mutation(["hello", "Hello"])

Your browser information:

User Agent is: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.142 Safari/537.36.

Link to the challenge:
https://learn.freecodecamp.org/javascript-algorithms-and-data-structures/basic-algorithm-scripting/mutations

try console.log(patt)

plus, don’t use g flag with test

If the regex has the global flag set, test() will advance the lastIndex of the regex. A subsequent use of test() will start the search at the substring of str specified by lastIndex ( exec() will also advance the lastIndex property). It is worth noting that the lastIndex will not reset when testing a different string.

I’ve removed the global flag and console.log(patt) provides this: /[arr.1]/i

I’m guessing that it matches arr.1 literally. But why does FCC let me pass the tests?

is this the regex you wanted? I provided you the documentation on how new RegExp works, and showed you why it doesnt pass (it is because "Hello" doesn’t contain any of the letters in the regex patt)
try using the documentation for fixing this line:

I’ve modified the code to:

function mutation(arr) {
  let patt = arr[1]
  let testRegex = new RegExp(patt, "i");
  let first = arr[0];
  var found = testRegex.test(first);
  return found;
  
}

mutation(["hello", "Hello"])

And I pass the tests where the order of the letters are same for both strings.

In other words:

mutation(["hello", "Hello"])

returns true but:

mutation(["floor", "for"])

returns false eventhough it should return true as well.

I think regex would be too complicated for this task and I should use another method. What do you think?

it is not complicated, but first you were using the square brackets for matching a class of characters, weren’t you?

the thing is, that the regex will match any of the included characters.

You can solve it with a regex, but you may need to think how to test for each individual letter in the word

1 Like

.test what it does is verify that your pattern is matched at least once, it stops there.

For example if your pattern is a set of characters [abcLpeEr] and your source string is "aloha" your code will stop at the first “a” and return true because a set of characters in regex what it does is assert that ANY character of the list is present.

What you want is a way to verify that ALL the characters from the 2nd argument are present in the string from the 1st argument.You COULD do it with RegExp (I know because I did it) but you have to know a little bit of set theory and the .match method of the String prototype.

Why? Because even if you were to extract all the characters that match your regex, you still need to:
1- Get rid of the duplicates
2- Consider that the match should be case-insensitve (a = A, e = E and so on)
3- Compare lengths of unique lowercase letters in set B vs the length of the matched unique lowercase letters from set A.

What you can do instead to do some sort of obscure ninja art is use positive lookaheads which is kind of an advanced topic:

A little example

^(?=.*H)(?=.*e)(?=.*l)(?=.*l)(?=.*o).*$

Remember that ^ means start of the line, $ means end of the line, the dot (.) character is a wildcard that means any character and * is for zero or unlimited amount of matches. (?=) is a capturing group with a positive look-ahead that means that whatever is behind should be followed by the next lookaheads; you can specify as many as you like together which kinda form a chained AND operator??? I didn’t understand why when I read it on the regex spec but at least I know that it works lol.

lexiheplWOzniaK matched against the aforementioned case-insensitive pattern yields:

index match sub-pattern
0 ^ followed by l (?=.*l)(?=.*l)
1 ^l followed by e (?=.*e)
2 ^lexi followed by H (?=.*H)
3 ^lexih followed by e (?=.*e)
4 ^lexihep followed by l (?=.*l)(?=.*l)
5 ^lexiheplW followed by O (?=.*o)
6 zniaK$ after all of the previous .*$

If one of the lookaheads were to fail, then the whole thing fails. So in order to construct the whole regex you’d have to do:

const pattern = new RegExp(
  '^' +
  args[1]
    .split('')
    .map(char => `(?=.*${char})`)
    .join('') +
  '.*$'
, 'im')

And now the whole function:

function mutation(arr) {
  const pattern = new RegExp(
    '^' +
    arr[1]
      .split('')
      .map(char => `(?=.*${char})`)
      .join('') +
    '.*$'
  , 'im')

  return pattern.test(arr[0]);
}
1 Like

wow this is amazing, thanks for such a detailed reply!