freeCodeCamp Challenge Guide: Mutations

Mutations


Problem Explanation

  • Return true if the string in the first element of the array contains all of the letters of the string in the second element of the array…

Relevant Links


Hints

Hint 1

  • If everything is lowercase it will be easier to compare.

Hint 2

  • Our strings might be easier to work with if they were arrays of characters.

Hint 3

  • A loop might help. Use indexOf() to check if the letter of the second word is on the first.

Solutions

Solution 1 (Click to Show/Hide)

Procedural

function mutation(arr) {
  const test = arr[1].toLowerCase();
  const target = arr[0].toLowerCase();
  for (let i = 0; i < test.length; i++) {
    if (target.indexOf(test[i]) < 0) return false;
  }
  return true;
}

Code Explanation

First we make the two strings in the array lowercase. test will hold what we are looking for in target.
Then we loop through our test characters and if any of them is not found we return false.

If they are all found, the loop will finish without returning anything and we get to return true.

Relevant Links

Solution 2 (Click to Show/Hide)

Declarative

function mutation(arr) {
  return arr[1]
    .toLowerCase()
    .split("")
    .every(function(letter) {
      return arr[0].toLowerCase().indexOf(letter) !== -1;
    });
}

Code Explanation

Grab the second string, lowercase and turn it into an array; then make sure every one of its letters is a part of the lowercased first string.

Every will basically give you letter by letter to compare, which we do by using indexOf on the first string. indexOf will give you -1 if the current letter is missing. We check that not to be the case, for if this happens even once every will be false.

Relevant Links

Solution 3 (Click to Show/Hide)

Recursive

function mutation([ target, test ], i = 0) {
  target = target.toLowerCase();
  test = test.toLowerCase();
  return i >= test.length
    ? true
    : !target.includes(test[i])
      ? false
      : mutation([ target, test ], i + 1);
}

Note that nesting ternaries this deeply is typically not recommended in professional code.

Solution 4 (Click to Show/Hide)
function mutation([elem1, elem2]) {
  const regex = new RegExp(`[^${elem1}]`, 'i');
  return !regex.test(elem2);
}

Code Explanation

Desconstruct the two elements of the array passed to the function and create a regular expression using the RegExp() constructor using a negated character set of all the first element’s characters. Adding the i flag makes the match case insensitive. The function returns the negated Boolean value of testing the regex with element two’s characters.

135 Likes

Here is another beginner solution:

function mutation(arr) {
  var newArr = [];
  var temp= 0;
  for (var i = 0; i < arr.length; ++i) {
    newArr[i] = arr[i].toLowerCase();
  }
  
  for (var j = 0; j < newArr[1].length; ++j) {
    if (newArr[0].indexOf(newArr[1][j]) < 0)
      return false;
  }
 return true;
}
28 Likes

Here’s another solution. In terms of skill I’d say it’s beyond beginner but not quite intermediate.

function mutation(arr) {
  arr.sort(function(a, b) {
    return a.length - b.length;
  });
  
  for (var i = 0, len = arr[0].length; i < len; i++) {
    if (arr[1].toLowerCase().indexOf(arr[0][i].toLowerCase()) < 0) {
      return false;
    }
  }
 
  return true;
}

This approach first sorts the two strings so that the string with the smallest length is in the first position. Then each character in the string with the smallest length (i.e., index 0) is tested against the characters in the string in the second position (i.e., index 1). If even one character is found not to match, the mutation function returns false. Otherwise mutation returns true. There’s also the necessary use of toLowerCase() to convert the strings to lowercase.

9 Likes

Here’s my solution. I resorted to adding booleans and checking if the sum matches the length of the second array element.

function mutation(arr) {
  var word = arr[0].toLowerCase();
  var letterToFind = arr[1].toLowerCase();
  var correctLetters = 0;
  for (var i = 0; i < letterToFind.length; i++) {
    correctLetters += (word.indexOf(letterToFind[i]) != -1);
  }
  return (correctLetters === letterToFind.length);

} 

mutation(["hello", "hey"]);
7 Likes

I like the approach, the only thing I would suggest is to iterate over arr[1] instead of arr[0] since we are only concerned about finding matches for the characters in arr[1], and instead of checking the indexOf of arr[1], check it for arr[0] to confirm all the matches. Everything else looks great!

btw what does the first part of your function do with sort? I’m not to great with functions within methods.

in freecodecamp “mutations”, one of the tests looks wrong “mutation([“Alien”, “line”]) should return true.” Can any one help me to know how it is true. Thank you :slight_smile:

Basic solution:

function mutation(arr) {
var check=0;
for(i=0;i<arr[1].length;i++){
check=arr[0].toLowerCase().indexOf(arr[1][i].toLowerCase());
if(check==-1){
return false;
}

}
return true;
}

5 Likes

another solution :

function mutation(arr) {
var text1= arr[0].toLowerCase().split("");
var text2= arr[1].toLowerCase().split("");
var len=arr[0].length,i,key,flag,j;

for(i=0;i<arr[1].length;i++){
  key=text2[i];
  {  for(j=0;j<len;j++)
      if(key==text1[j])
         {   flag=true;
         break; }
      else {flag=false;
           }
  }
  if(flag===false)
    {break;}
  }

return flag;
}

mutation([“hello”, “hey”]);

function mutation(arr) {
  word = arr[0].toLowerCase();
  letters = arr[1].toLowerCase().split("");
  wrong = false;
  
  
  letters.map(function(letter){
      if(word.indexOf(letter) == -1){
      wrong = true; 
      }
    
  });
  
  if (wrong){
    return false;
  }
 
  return true;
}

mutation(["hello", "neo"]);

Another solution.

2 Likes

My Solution is simply this:

function mutation(arr) {
for(var i = 0; i <= arr[1].length -1; i++){
if (arr[0].toLowerCase().indexOf(arr[1][i].toLowerCase()) == -1)
return false;
}
return true;
}

8 Likes

This is where I was headed. I wasn’t aware I could use arr[1][i] to look at each individual letter. For some reason I thought that indexOf would search the string for any number of combinations, but I was probably asking a bit much from the method. Thanks for the assist!

2 Likes

You are welcome hart143

The world Alien contains the letters: l, i , e, and n. The word Line contains the letters: l, i, e, and n.

Hi all,

For the basic solution how come we do not need to convert stings to individual characters with.split() before utilizing .indexOf()?

5 Likes

I ended up taking a round about way – initially tried converting the array to separate strings like the Basic Code Solution, but got stuck, so went back to keeping it as an array:

  arr[0] = arr[0].toLowerCase();
  arr[1] = arr[1].toLowerCase();
  var result = [];
  for (i=0; i<arr[1].length; i++) {  
    result[i] = arr[0].indexOf(arr[1][i]);
  } 
  var resultArray = result.filter(function(val) {
    return val===-1;
  });
  if (resultArray[0]===-1) {
    return false;
  } 
  return true; 
}
1 Like

I like this solution it is very similar to what I wanted to write but i do not understand why you put that “arr[1].length -1” why not just “arr[1].length”. I though I had understood for loops but these exercises have just shown me that what I learnt earlier does not even scratch the surface. when I see all these solutions, they seem to go againts everything i tought for loops should look like!! for loops are so complex and broad. I really dont like them. It seems like just when you think you get it, there is another BUT…

1 Like
function mutation(arr) {
    var a = arr[0].toLowerCase().split('');
    var b = arr[1].toLowerCase().split('');
    while (b.length) {
        if (a.indexOf(b[0]) >= 0) {
            b.splice(0, 1);
        }
        else if (a.indexOf(b[0]) < 0) {
             return false;
        }     
     }
     return true;
}
1 Like

Beginner long solution:
function mutation(arr) {
var x = arr;
var y = [];
for (k=0;k<arr.length;k+=1){
x[k]=x[k].toLowerCase();
}

for(var i=0;i<x[1].length;i+=1){
for(var j=0;j<x[0].length;j+=1){
if (x[1][i]==x[0][j]){
y.push(1);
break;
}
}
}

for (var l=0;l<y.length;l+=1){
if(y.length == x[1].length){
return true;
}
}
return false;
}

mutation([“hello”, “hey”]);