Mutations - Right answer but dumb code

Tell us what’s happening:

Your code so far


function mutation(arr) {
  
  for(let key in arr){  
    arr[key] = arr[key].toLowerCase();
  }

  for(var i = 0; i < arr[1].length; i++){
    var ok = 0;
    for(var j = 0; j < arr[0].length; j++){
      console.log(arr[1][i]); 
      console.log(arr[0][j]);
      
      if(arr[1][i] == arr[0][j]){
        console.log("*");
        ok = 1;
     }
    }
    if(ok == 0)
      return false;
  }

  return true;
}

mutation(["Alien", "line"])

Your browser information:

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

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

So I wrote this code for the Mutations challenge and I want to know your opinion. Is it a good code or it’s all over the place ? It took me a while.

First of all, good job on making it on your own don’t worry if it took you a while or not what is important is that you made it :grinning:
Secondly, the solution is good and straight to the important point, also strive for clean and understandable
Lastly, remove the console.logs they make it harder to analyze :smile:

I gave it a try and came up with another solution which can be more confusing depending on your experience (which probably goes against what I said in my second point :sweat_smile:).

I will leave it here with an explanation on the thought process, hope it helps you learn a bit more.

function mutation(arr) {

  const smallerWord = arr[0].length <= arr[1].length
    ? arr[0]
    : arr[1]
  const biggerWord = smallerWord >= arr[0].length
    ? arr[1]
    : arr[0]
  const biggerWordArr = biggerWord.split('')
  const smallerWordArr = smallerWord.split('')

  return smallerWordArr
    .every(char => 
      biggerWordArr.indexOf(char) >= 0
    )
}

mutation(["Alien", "line"])

In code, you always want to try and make as little iterations as possible while keeping the code comprehensive so let’s grab that statement and run with it.

If you look at the challenge you need to find if all the characters of the smaller word are used in the bigger word so let’s start by finding which one is the smaller word.

  const smallerWord = arr[0].length <= arr[1].length
    ? arr[0]
    : arr[1]
  const biggerWord = smallerWord >= arr[0].length
    ? arr[1]
    : arr[0]

After we have that we get two variables with the word but, to iterate in a loop we need an array, so let’s make one

  const biggerWordArr = biggerWord.split('')
  const smallerWordArr = smallerWord.split('')

So now that we have an array we take advantage of the method every that tries to find if a statement is true for all of an array if it is it will return a true, if it isn’t well, return a false.

We want the least iterations possible so we iterate the smaller word array and our statement will be “I want to check if each character is present inside of the bigger word array” which translate to code to biggerWordArr.indexOf(char) >= 0.

return smallerWordArr
    .every(char => 
      biggerWordArr.indexOf(char) >= 0
    )

We return immediately but we could’ve put it in a variable ok as you did and then return it.

Note Improvements on it are incentivized :smile:
Note 2 This is by no means a “correct” answer or the most “optimal” one, it’s just another way of doing the same thing while doing fewer iterations while still keeping the code clean

Edit: Longer would be a better wording than bigger but now I’m to lazy to change it he…heheheh

That is not what the challenge instructions state. It has nothing to do with bigger/longer or smaller/shorter words. It states to make sure the string in the first element of the array contains all of the letters of the string in the second element of the array.

A test case which is currently missing from the tests would be:

mutation(["ate", "date"] should return false

It should return false because of all of the letters of the first element of the array (“ate”) does not contain all of the letters of the string in the second element of the array (“date”). The first string does not contain the “d” that is in the second string. Your function returns true because it is only validating that the letters “a”, “t”, and “e” are in “date” and they are, but that is not what the challenge is expecting your to test.

Another test case in which your function would fail is another missing test (see below):

mutation(["Tiger", "Zebra"]) should return ‘false’

It should return false for obvious reasons, but because your function uses >= and >= when comparing length to determine smallerWord and biggerWord, smallerWord and biggerWord end up being the same word, so your function would always return true if the two words have the same length regardless of what the letters of the words are.

Lastly, a test case in which your function would fail is another missing test (see below):

`mutation(["Noel", "Ole"])` should return `true`

It should return true because you should be ignoring case as the challenge example demonstrate. All the letters “o”, “l” and “e” of “Noel” are present in “Ole”. The “o” is lowercase, but that does not matter.

I am going to create a pull request right now, to make sure these 3 new tests are added to make this challenge’s test correctly reject invalid solutions.

On a side note, it is not necessary to split biggerWord and smallerWord into an array because strings have the indexOf method just like arrays do.

1 Like

You’re right, it seems I ended up fitting a solution for the tests instead of what the challenge actually states

The check for the bigger word in that scenario should’ve been smallerWord === arr[0] to avoid the same value from being selected

The lowercase can be fixed by adding .toLowerCase() before assigning to a variable

On the side note, you would all the same need to split for the every but not for the indexOf since it’s available for strings like you mention

After revision, a solution that actually fits on what is asked and includes the 3 new tests could be:

function mutation(arr) {
  const firstElement = arr[0]
    .toLowerCase()
  const secondElement = arr[1]
    .toLowerCase()

  return secondElement
    .split('')
    .every(char => 
      firstElement.indexOf(char) >= 0
    )
}

mutation(["Alien", "line"])

Thank you for your feedback, glad to know that the tests will be updated and hopefully I haven’t misled many people :sweat_smile:

1 Like

In general, we prefer not to post full working solutions in responses to questions to avoid spoiling a solution for someone who views the thread looking for help and not wanting to see a solution yet. I have hidden your code. In the future, just describe your algorithm or use pseudo-code.

1 Like