Mysterious Organism Challenge Project (JavaScript)

Enjoyed this. Includes a solution to the follow-on challenge to identify the two most similar specimens.

1 Like

This is my code, it would be great to get some feedback! :grin:

// Returns a random DNA base
const returnRandBase = () => {
  const dnaBases = ['A', 'T', 'C', 'G']
  return dnaBases[Math.floor(Math.random() * 4)] 
}

// Returns a random single stand of DNA containing 15 bases
const mockUpStrand = () => {
  const newStrand = []
  for (let i = 0; i < 15; i++) {
    newStrand.push(returnRandBase())
  }
  return newStrand;
}

const pAequorFactory = (specimenNum, dna) => {
  return {
   specimenNum,
   dna,
   mutate() {

     //Select a random element in the dna array
   let selectElement = Math.floor(Math.random() * array.  
   length);

     //Change the current base to a different one 

    if (selectElement === 'A') {
    this.dna.splice(selectElement, 0, 'T');
  } else if (selectElement === 'T') {
    this.dna.splice(selectElement, 0, 'A');
  } else if (selectElement === 'G') {
    this.dna.splice(selectElement, 0, 'C');
  } else {
    this.dna.splice(selectElement, 0, 'G');
  }
     //Return the object's dna 

return this.dna;
   }, 

   compareDna(secondPaequor) {
     let identicalBases = [];

     //Using one loop only, since we only need to compare 
     //values that are in the same position 

      for (let i = 0; i < this.dna.length; i++) {
        if (this.dna[i] === secondPaequor[i]) {
         identicalBases.push([i]);
        console.log(identicalBases);

      //Take the number of identical bases (the new array 
      //length), divided by the total number of bases (15) 
      //and multiply by 100
      //Use the .toFixed() method to limit the number of 
      //decimal places 
 }
}
   
let percentDna = (identicalBases.length/15 * 100).toFixed();
console.log(percentDna);
return console.log(`Specimen #${this.specimenNum} and Specimen #2 have ${percentDna}% DNA in common.`);
    },

    willLikelySurvive() {
      //Check every element of the dna array and add any C 
      //or G elements to a new array
      let cGBases = [];
      for (let i= 0; i < this.dna.length; i++) {
        if (this.dna[i] === 'C' || this.dna[i] === 'G') {
          cGBases.push([i]);
        } 
      }
      if (cGBases.length > 8) {
        return true;
      } else {
        return false;
      }
   //60% of 15 is 9
   //If the array.length is > 8 return true (since arrays start counting at 0)
   //Otherwise return false 
    }
   }
  };

//Use the factory f(x) to create 30 instances of pAequor
//New empty array 
let paequorArray = [];  
//Specimen Number Counter
let specimenNumCounter = 1;

while (paequorArray.length < 30) {
  //Call the factory function with the parameters
let newPaequor = pAequorFactory(specimenNumCounter, mockUpStrand());
//Call the willSurvive method and if it returns true, add it to the array 
if (newPaequor.willLikelySurvive()) {
   paequorArray.push(newPaequor);
}
//Increment the specimen number counter
  specimenNumCounter++;
}

console.log(paequorArray);



Hi all, just finished this assignment, took me quite a while.

I could really use some pointers whether I’ve used the reduce method correctly and whether it will, in fact, return the maximums result in the array of objects. Thanks in advance to any who takes the time to take a look. Much love

1 Like

I’m having a serious doubts about my mutate function. The entire code can be found here

But the mutate function in particular is eating at my brain. My problem is it generally works but it appears my check for if the pairs are different just doesn’t work at all. About a quarter of the time it just doesn’t mutate anything.

Here’s the code:

mutate () {
          const index = Math.floor(Math.random() * this.dna.length);
          let oldBase = this.dna[index];
          let newBase = '';
          //ensures the base is different NOT WORKING
          do {
            newBase = returnRandBase();
          } 
          while (newBase === oldBase);
          this.dna[index] = newBase;
        }

My do…while appears to just not do anything.

Any Ideas?

1 Like

This challenge was so difficult !! and good!
after I solved much of it now, I feel different :rofl:
but it’s so freshening to figure out the solution.
my code is messy! please get me some good feed back on that.
here is my work. https://gist.github.com/MAHMOUD-IDRIS/d1a4f64b711ace9c9f5757e9b3ab3ae4
Please check.
Thanks

Hi!
I couldn’t find the solution to changing the newBase if the generated base is the same as the existing one.
your code here only switches the newBase before it applies it. it doesn’t check if it’s identical to the existing one.
the selectElement is a number and a is not === to ‘A’.

if I didn’t understand your code please explain!

Hi @script6508472340, thanks so much for catching that. Here’s my refactored solution, it should be working as expected now:

// Returns a random DNA base
const returnRandBase = () => {
  const dnaBases = ['A', 'T', 'C', 'G']
  return dnaBases[Math.floor(Math.random() * 4)] 
}

// Returns a random single stand of DNA containing 15 bases
const mockUpStrand = () => {
  const newStrand = []
  for (let i = 0; i < 15; i++) {
    newStrand.push(returnRandBase())
  }
  return newStrand;
}

const pAequorFactory = (specimenNum, dna) => {
  return {
   specimenNum,
   dna,
   
   // Function that randomly changes one element in the array
   mutate() {

    // Select a random element in the dna array
    let selectElement = returnRandBase();
  
  // Get the index of that random element
  let index = array.indexOf(selectElement);

  // Change the current base to a different one, checking that it's different from the current one 

  if (selectElement === 'A') {
    this.dna.splice(selectElement, 0, 'T');
  } else if (selectElement === 'T') {
    this.dna.splice(selectElement, 0, 'A');
  } else if (selectElement === 'G') {
    this.dna.splice(selectElement, 0, 'C');
  } else {
    this.dna.splice(selectElement, 0, 'G');
  }
    // Return the object's dna 

return this.dna;
   }, 

   compareDna(secondPaequor) {
     let identicalBases = [];

    // Using one loop only, since we only need to compare values that are in the same position 

      for (let i = 0; i < this.dna.length; i++) {
        if (this.dna[i] === secondPaequor[i]) {
         identicalBases.push([i]);
        console.log(identicalBases);

      // Take the number of identical bases (the new array length), divided by the total number of bases (15) and multiply by 100
    // Use the .toFixed() method to limit the number of decimal places 
 }
}
   
let percentDna = (identicalBases.length/15 * 100).toFixed();
console.log(percentDna);
return console.log(`Specimen #${this.specimenNum} and Specimen #2 have ${percentDna}% DNA in common.`);
    },

    willLikelySurvive() {
      //Check every element of the dna array and add any C 
      //or G elements to a new array
      let cGBases = [];
      for (let i= 0; i < this.dna.length; i++) {
        if (this.dna[i] === 'C' || this.dna[i] === 'G') {
          cGBases.push([i]);
        } 
      }
      if (cGBases.length > 8) {
        return true;
      } else {
        return false;
      }
   /* 60% of 15 is 9
   If the array.length is > 8 return true (since arrays start counting at 0)
   Otherwise return false 
   */
    }
   }
  };

// Use the factory function to create 30 instances of pAequor
// New empty array 
let paequorArray = [];  

// Specimen Number Counter
let specimenNumCounter = 1;

while (paequorArray.length < 30) {
  // Call the factory function with the parameters
let newPaequor = pAequorFactory(specimenNumCounter, mockUpStrand());
// Call the willSurvive method and if it returns true, add it to the array 
if (newPaequor.willLikelySurvive()) {
   paequorArray.push(newPaequor);
}
// Increment the specimen number counter
  specimenNumCounter++;
}

console.log(paequorArray);



Hi @ktsotras, I tested out your code as I am a bit stumped on how to actually use the function compareDna.

When I ran your code on compareDna by calling

newPaequor.compareDna([paequorArray]);

I get the message TypeError: Cannot read property ‘length’ of undefined
if(length != otherDNA.length)

I get a similar error with the solution code and my code as well, so I was wondering how this compareDNA function is actually meant to work?

I also tried running your code with the compareBatchDna function, but I get a print out of as many pairs of empty arrays as there are instances of of pAequor in the willLikelySurvive array.

Please do correct me if I’ve misunderstood, the reason why I’m asking is because I’m trying to complete the extensions but really getting stuck on these points!

Thank you in advance :grinning:

My code with the complementStrand function extension:

// Returns a random DNA base
const returnRandBase = () => {
  const dnaBases = ['A', 'T', 'C', 'G']
  return dnaBases[Math.floor(Math.random() * 4)] 
}

// Returns a random single stand of DNA containing 15 bases
const mockUpStrand = () => {
  const newStrand = []
  for (let i = 0; i < 15; i++) {
    newStrand.push(returnRandBase())
  }
  return newStrand;
}

const pAequorFactory = (specimenNum, dna) => {
  return {
   specimenNum,
   dna,
   
   // Function that randomly changes one element in the array
   mutate() {

    // Select a random base in the dna array
    let selectElement = returnRandBase();
  
  // Get the index of that random base
  let index = array.indexOf(selectElement);

  // Change the current base to a different one, checking first that it's different from the current one 

  if (selectElement === 'A') {
    this.dna.splice(selectElement, 0, 'T');
  } else if (selectElement === 'T') {
    this.dna.splice(selectElement, 0, 'A');
  } else if (selectElement === 'G') {
    this.dna.splice(selectElement, 0, 'C');
  } else {
    this.dna.splice(selectElement, 0, 'G');
  }
  // Return the object's mutated dna 

return this.dna;
   },  

  // Compare the DNA sequences of the current pAequor to a different P.aequor passed in as a parameter
// Computes how many bases are identical and in the same location 
   compareDna(secondPaequor) {
     let identicalBases = [];

    // Using one loop only, since we only need to compare values that are in the same position 

      for (let i = 0; i < this.dna.length; i++) {
        if (this.dna[i] === secondPaequor.dna[i]) {
         identicalBases.push([i]);
        console.log(identicalBases);

      // Take the number of identical bases (the new array length), divided by the total number of bases (15) and multiply by 100
    // Use the .toFixed() method to limit the number of decimal places 
 }
}
   
    let percentDna = (identicalBases.length/this.dna.length * 100).toFixed();
       console.log(percentDna);
         return console.log(`Specimen #${this.specimenNum} and Specimen #${secondPaequor.specimenNum} have ${percentDna}% DNA in common.`);
    },

    willLikelySurvive() {
      //Check every element of the dna array and add any C 
      //or G elements to a new array
      let cGBases = [];
      for (let i= 0; i < this.dna.length; i++) {
        if (this.dna[i] === 'C' || this.dna[i] === 'G') {
          cGBases.push([i]);
        } 
      }
      if (cGBases.length > 8) {
        return true;
      } else {
        return false;
      }
   /* 60% of 15 is 9
   If the array.length is > 8 return true (since arrays start counting at 0)
   Otherwise return false 
   */
    },
  complementStrand(dna) {
  let strand2 = [];
  for (let i = 0; i < this.dna.length; i++) {
    if (this.dna[i] === 'T') {
      strand2.push('A');
    } else if (this.dna[i] === 'A') {
      strand2.push('T');
    } else if (this.dna[i] === 'C') {
      strand2.push('G');
    } else {
      strand2.push('C');
    }
  } console.log(strand2);
}
   }
  };

// Use the factory function to create 30 instances of pAequor
// New empty array 
let paequorArray = [];  

// Specimen Number Counter
let specimenNumCounter = 1;

while (paequorArray.length < 30) {
  // Call the factory function with the parameters
let newPaequor = pAequorFactory(specimenNumCounter, mockUpStrand());
// Call the willSurvive method and if it returns true, add it to the array 
if (newPaequor.willLikelySurvive()) {
   paequorArray.push(newPaequor);
   //newPaequor.complementStrand([paequorArray]);
   //newPaequor.compareDna([paequorArray]);
}
// Increment the specimen number counter
  specimenNumCounter++;
};
//console.log(paequorArray);


The error I get when I call compareDna is on line 54:

"TypeError: Cannot read property ‘0’ of undefined at Object.compareDna

if (this.dna[i] === secondPaequor.dna[i]

@ktsotras nevermind, I got it. Here’s a link to my project with extensions, I would love any feedback!

This is the first JS project that I solved entirely on my own, that feels so rewarding! :blush:
Breaking down the steps for each requirement before actually starting to write any code truly made a difference if I compare with how I handled past projects.
Only left out the "find the two most related instances of pAequor " project extension, as after searching for some inspiration in the solutions shared here, I feel like this is beyond my understanding for now. Maybe I’ll finish it at a later time after revisiting some methods like reduce() more into depth…

1 Like

Hi all.

This is my take on this project:

I completed all additional challenges. Feel free to comment.

Happy coding!

Hi @sullivankevint,

I checked the output of each step by adding some console.log() as below:

mutateTest () {
            const index = Math.floor(Math.random() * this.dna.length);
            console.log(index);
            let oldBase = this.dna[index];
            console.log(oldBase);
            let newBase = '';
            //ensures the base is different NOT WORKING
            do {
              newBase = returnRandBase();
              console.log(newBase);
            } 
            while (newBase === oldBase);
            this.dna[index] = newBase;
        }

and it worked absolutely fine. After a few goes, when the condition newBase === oldBase was met, your method called returnRandBase() again until newBase was different than oldBase.

1 Like

I started the JavaScript tutorials back in November or December, then took off for half a year. When I came back, this project was up to do, so here’s my solution. I had forgotten all about array methods and backtick strings, but I’m just going to forge forward without going out of my way to review, since most of what the tutorials covered up to this point also applies to C/C++, which I already know.

I agree with you. Also they say find the most related instances of pAequor but they don’t specify among which. I concluded they must have meant among the thirty surviving specimens in the array to study later , but it isn’t clear.

This is my code so far

I’m trying to make a function to find the most similar pAequor specimens among the 30 surviving ones but I’m lost as to how to finish it. Anyone can give me a hint? I have compared all specimens against each other but I don’t know what to do with the result .

//find most related instances of pAequor.

const findMostRelated = () => {

arrMatches = [];

const survivors = survivors30();

for (let i = 0; i < survivors.length; i++) {

    for (let j = 0; j < survivors.length; j++) {

        const matches = survivors[i].compareDna(survivors[j]);

        arrMatches.push(matches)

    }

}

return arrMatches

};

Looking back at this with fresh eyes.

My while statement has ‘===’ in place of ‘==’

That’d be my issue

Hi guys!
I had fun working on this challenge. Check out my solution here:
Mystery Organism solution

You don’t need the mutate() method but you are supposed to create an array containing 30 pAequors that WILL survive.

As far as i see, yours just returns an array of 30 random pAequor samples…

2 Likes

Welcome to the forums @darowebdeveloper

I believe it’s a combination of both… that’s what OR means, that ‘G’ OR ‘C’ are both valid to reach the neccesary 60%