Mysterious Organism Project

Link to Exercise: https://www.codecademy.com/practice/projects/mysterious-organism

// 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 = (number, array15) => {
 let specimenNum = number;
 let dna = mockUpStrand();
  return {specimenNum, 
          dna, 
          mutate(){
          let random = this.dna;
     let i = Math.floor(Math.random()*15);
            let base = random[i]
            if (base === 'A'){
               return (random[i] = 'T', console.log(random));
              
           } else if(base === 'T'){
                     return (random[i] = 'A', console.log(random));
                     } else if (base === 'C') {
                   return (random[i] = 'G', console.log(random));
           } else {return (random[i] = 'C', console.log(random));}          
          }
         
         };
}


let test = pAequorFactory(1, mockUpStrand());
console.log(test);
test.mutate();

image

The above is my output… Why does my code randomly say mutate: [Function:mutate]}

Hello, @bhb23955.

The mutate() function is part of the test object you created with your pAequorFactory() function. When you console.log(test) it prints the object as you’ve seen in your output. If you only want to see a specific property of the object you can access them individually: console.log(test.dna) for example will only log the dna property’s value to the console.

For future posts, please review How do I format code in my posts?
Following the guidelines in that topic will make your code appear as it does now after I formatted it.
Happy coding!

1 Like

Okay that makes sense!

Thanks

1 Like

Hello,

I am stuck here too.

for me here, console.log(test) logs an object, but when i try to call the value of property dna, I get undefined. I am using the code indicated above i think. console.log(test.dna)

here is a screenshot of the console and the code is below


the code also produces red brackets in a couple places.

// 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 = (number, array15) => {
  let specimenNum = number;
  let dna = array15;
  return {
    specimenNum,
    dna,
    mutate() {
      let random = this.dna;
      let i = Math.floor(Math.random() * 15);
      let base = random[i];
      if (base === 'A') {
        return (
          random[i] = 'T',
          console.log(random));
      } else if (base === 'T') {
        return (
          random[i] = 'A',
          console.log(random));
      } else if (base === 'C') {
        return (
          random[i] = 'G',
          console.log(random));
      } else {
        return (
          random[i] = 'C',
          console.log(random));
      }
    },
    compareDNA(newOrg) {
      let orgOne = this.dna;
      let orgTwo = newOrg;
      let total = 0;
      let length = 16;
      for (let i = 0; i < length; i++) {
        if (orgOne[i] === orgTwo[i]) {
          total = total + 1
        }
      }
      return (
        console.log('Thanks you for using our service! \n \nSpecimen #1 and Specimen #2 have ' + total / 15 + '% DNA in common')
      )
    },
  };
}

let sample = ['A', 'A', 'A', 'C', 'A', 'T', 'A', 'T', 'C', 'A', 'A', 'G', 'G', 'T', 'A'];


let test = []

test.push(pAequorFactory(1, mockUpStrand()));
//console.log(test);
console.log(test.dna)

Eurika! It works, the sad part is, I’m not sure hwere the difference is yet

// 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 = (number, array15) => {
  let specimenNum = number;
  let dna = mockUpStrand();
  return {
    specimenNum,
    dna,
    mutate() {
      let random = this.dna;
      let i = Math.floor(Math.random() * 15);
      let base = random[i];
      if (base === 'A') {
        return (random[i] = 'T', console.log(random));
      } else if (base === 'T') {
        return (random[i] = 'A', console.log(random));
      } else if (base === 'C') {
        return (random[i] = 'G', console.log(random));
      } else {
        return (random[i] = 'C', console.log(random));
      }},
    compareDNA(newOrg) {
      let orgOne = this.dna;
      let orgTwo = newOrg;
      let total = 0;
      let length = 16;
      for (let i = 0; i < length; i++) {
        if (orgOne[i] === orgTwo[i]) {
          total = total + 1
        }
      }
      return (
        console.log('Thanks you for using our service! \n \nSpecimen #1 and Specimen #2 have ' + total / 15 + '% DNA in common')
      )
    },
    
  }
}

let test = pAequorFactory(1, mockUpStrand());
console.log(test);
test.mutate();
console.log(test.dna);

Mutate works, but i can not seem to access compareDNA. there must be an error in the code but i cant find it. The compareDNA text has not tinted blue indicating some kind of issue.

Hello @jaredgibb8852281658, and welcome to the forums!

let test = []

test.push(pAequorFactory(1, mockUpStrand()));

versus

let test =  pAequorFactory(1, mockUpStrand());

In your first attempt, test is an array that contains a pAequorFactory object. In your second, test is a variable that has a pAequorFactory object assigned to it. console.log(test[0].dna) would have printed the dna property to the console.

Thank you!! That makes sense! I was not invoking the correct object from the the array as i left off the index!

I kept testing test.dna[0]

I dont want the dna index of 0 of all test items. I want the first test items dna poperty

i tested and can confirm i have made both of these work.
Screen Shot 2020-04-29 at 3.33.03 PM

now on to the next step and figuring out why i have red brackets and cant make compareDNA work! :rofl:

A few observations:
What is the point of return in these lines:

Also in your mutate() method, you randomly select a location in the dna array to change, but the change is an arbitrary value rather than a random selection. You have a returnRandBase method that could be used for that. While it’s not necessarily a requirement for the project to do it that way, I’d encourage you to try implementing it.

1 Like

Keep in mind that newOrg will need to be pAequorFactory object, and it has the same properties that have to be accessed the same way as the original pAequorFactory object that you are calling the compareDNA method on.

1 Like

Thank you! I will take this FB and try to implement. I’ll be back tomorrow with updates. Thank you!!

1 Like

UPDATE: I solved my own problem. Yay!

I was going about solving the problem in a strange way, and creating each object as a mutation of the last. When I created objects as fresh instances, it solved the issue. If you care to see the evolution of the code, it is preserved in the edits.

Here’s where I ended up…
at the bottom you will see output of the last few objects in the list, as well as the mutate called upon the last specimen (for easy comparison) and also the compareDNA results. Took a few hours, but well worth it!


function pAequorFactory(specNum, dna)  {
  return {
    specimenNum: specNum,
    dna: dna,
    mutate() {
      let mutateBase = Math.floor(Math.random() * 15);
      let newDna = returnRandBase();
      if(this.dna[mutateBase] !== newDna) {
        this.dna[mutateBase] = newDna;
      } else {
        this.mutate();
      }
      return this.dna;
    },
    compareDNA(organism) {
      let sameDNA = 0;

      for (let i = 0; i < 15; i++) {
        if (this.dna[i] === organism.dna[i]) {
            sameDNA++;
        }
      }
      
      sameDNA /= 0.15;
      sameDNA = sameDNA.toFixed(2);
      
      console.log(`Specimen #${this.specimenNum} and specimen #${organism.specimenNum} have ${sameDNA}% DNA in common`);
    },
    willLikelySurvive() {
      let cgVals = [];
      this.dna.forEach(element => { if (element=== 'C' || element === 'G') cgVals.push(element)});
      let cgNum = cgVals.length;
      let survival = cgNum / .15;
      survival = survival.toFixed(2);

      
      if (survival >= 60) {
        console.log(`the number of C and G bases is: ${cgNum} and the percentage is ${survival}%`);
        return true;
      } else {
        return false;
      }
    } //end objects
  }
};


let pAequor = []

for (i = 0; i < 30; i++) {
pAequor[i] = pAequorFactory(i + 1, mockUpStrand());

if (pAequor[i].willLikelySurvive()) {
  console.log(`specimen number: ${pAequor[i].specimenNum}, DNA sequence: `, pAequor[i].dna);
  console.log(' ');
} else {
  i--;
  pAequor[i] = pAequorFactory(i + 1, mockUpStrand());
}
}


console.log(`Mutation alert! Specimen #${pAequor[29].specimenNum} has undergone mutation. Here is the new Gene sequence: `, pAequor[29].mutate());


pAequor[25].compareDNA(pAequor[13]); 

OUTPUT ROUND 1:
the number of C and G bases is: 9 and the percentage is 60.00%
specimen number: 29, DNA sequence: [ β€˜G’, β€˜G’, β€˜A’, β€˜C’, β€˜A’, β€˜T’, β€˜T’, β€˜C’, β€˜C’, β€˜C’, β€˜G’, β€˜C’, β€˜A’, β€˜T’, β€˜C’ ]

the number of C and G bases is: 9 and the percentage is 60.00%
specimen number: 30, DNA sequence: [ β€˜G’, β€˜G’, β€˜T’, β€˜G’, β€˜T’, β€˜T’, β€˜C’, β€˜C’, β€˜C’, β€˜A’, β€˜A’, β€˜G’, β€˜C’, β€˜G’, β€˜T’ ]

Mutation alert! Specimen #30 has undergone mutation. Here is the new Gene sequence: [ β€˜A’, β€˜G’, β€˜T’, β€˜G’, β€˜T’, β€˜T’, β€˜C’, β€˜C’, β€˜C’, β€˜A’, β€˜A’, β€˜G’, β€˜C’, β€˜G’, β€˜T’ ]
Specimen #26 and specimen #14 have 26.67% DNA in common

OUTPUT ROUND 2:

the number of C and G bases is: 9 and the percentage is 60.00%
specimen number: 29, DNA sequence: [ β€˜A’, β€˜T’, β€˜T’, β€˜G’, β€˜G’, β€˜C’, β€˜A’, β€˜G’, β€˜C’, β€˜C’, β€˜T’, β€˜C’, β€˜G’, β€˜T’, β€˜G’ ]

the number of C and G bases is: 9 and the percentage is 60.00%
specimen number: 30, DNA sequence: [ β€˜C’, β€˜C’, β€˜C’, β€˜C’, β€˜A’, β€˜C’, β€˜A’, β€˜T’, β€˜C’, β€˜C’, β€˜T’, β€˜C’, β€˜T’, β€˜C’, β€˜T’ ]

Mutation alert! Specimen #30 has undergone mutation. Here is the new Gene sequence: [ β€˜C’, β€˜C’, β€˜C’, β€˜C’, β€˜A’, β€˜C’, β€˜A’, β€˜T’, β€˜C’, β€˜T’, β€˜T’, β€˜C’, β€˜T’, β€˜C’, β€˜T’ ]
Specimen #26 and specimen #14 have 33.33% DNA in common

1 Like

some thoughts/observations


for (i = 0; i < 30; i++) {

the i there is global (missing let)


  } else {
    i--
    pAequor[i] = pAequorFactory(i + 1, mockUpStrand())

that’ll overwrite the previous one which you had already locked in so to speak. you could get unviable specimen from that.


for (i = 0; i < 30; i++) {

the condition you’re really looking for there is while your array of specimen has a size less than 30

while ( ...

and then you could append (push) to the array when finding a successful specimen, and you can use the length of the array to figure out what id to use so you wouldn’t need to keep a variable for counting


      if (survival >= 60) {
        console.log(`the number of C and G bases is: ${cgNum} and the percentage is ${survival}%`)
        return true
      } else {
        return false
      }

I’d want that to be this instead, maybe the print can be moved or removed

return survival >= 60

      let survival = cgNum / 0.15
      survival = survival.toFixed(2)

could this be done with integers instead? the rounding there looks a bit fishy to me.
where is 0.15 coming from? is that because the size is 15? what if the size changes?

this avoids floating point operations and rounding, and uses the length of the array

100 * cg_count > 60 * length

      this.dna.forEach(element => { if (element === 'C' || element === 'G') cgVals.push(element) })

use array.filter!
I like the use of array.length to count. it avoids having to sum
but you could also increment a variable (count++) instead of pushing to an array, and then forEach would make sense


      sameDNA /= 0.15
      sameDNA = sameDNA.toFixed(2)

same there, there’s a length you can look at, don’t need to hard-code 0.15
the rounding is fair though, because it’s for displaying

Thanks for the comments and tips. I am still fairly new to all this and appreciate the feedback so I can write cleaner code in the future. I have made a few tweaks now that implemented some of those, such as using length to calculate the percentage displays rather than hard coding, slightly reworking the pAequorFactory call, and adding the let before i variable.

My reasoning on using a for loop rather than while is that I could lower the iteration number if the pAequorFactory creation failed the survivability test so that I would get 30 viable specimens. But I think I see what you are saying regarding making the results array length the test length. Will give that a go…

Same for using a count++ on the forEach. Makes sense. I will try it with the filter as well to see how that goes.

re: return survival >= 60… much cleaner. Thanks for that!