Mysterious Organism Challenge Project (JavaScript)

Hi,

Here you can find my solution to the problem: https://github.com/Mikheltodd/Mysterious-Organism.git

It was very interesting (specially the part where we had to create new specimens that will survive). And it was curious that, when you mutate a specimen, it could generate a strand that will not survive. I guess it has to do with how long the strand is.

I also included code for comparing all the specimens to find the most related ones using nested for (the inner one starting from the value of the outer one).

Regards,

Here is my solution!

My solution to the mysterious organism challenge:
https://github.com/gingergaz/codecademy_sharing/raw/main/mysterious_organism.js
Bring on the next one!!

I was looking for the most recent post that has the “most related instances” snippet and found yours. I have a few ideas, let me know what you think:

  1. for your second for loop, you can initialise your j to i+1 instead of 0. That way you’re skipping all the pairs that you’ve already compared and you’re skipping comparing strands to themselves. (eg once specimen 1 and 2 are compared, no need to go through specimen 2 and 1 again) . I know you have that control flow to skip those iterations, but it might be more efficient to just not go through it at all.
  2. for larger sample sizes, there’s a possibility that there will be more than one pair that has close relationship. You might want to consider pushing those other pairs too.

This is what I have in mind

function getcloseRelationDna(batch) { var maxRelation = 0, closeStrands = [], relation; for (let i=0; i<batch.length; i++) { for (let j=i+1; j<batch.length; j++){ relation = batch[i].compareDNA(batch[j]); if (relation >= maxRelation) { if (relation !== maxRelation) { maxRelation = relation; closeStrands = []; } closeStrands.push([batch[i], batch[j]]) } } } return closeStrands; }

There might be a better solution than what I have. Let me know what you think.

I really like that solution. Only one point i would consider improving:
Currently your getCloseRelation returns an array of pAequors and the naming of the array as well as the function suggests that all Strands in this array are closely related to one another. While in reallity only the adjacent ones (closeStrands[0] to closeStrands[1], closeStrands[2] to closeStrands[3] etc.) are necessarily closely related.
So my suggestion would be populating this array with objects of the form

{
relationPercentage: 
firstPAequor:
secondPAequor:
}

Or if you dont care about the percentage outside your function, store the related ones as arrays in your array. Just to make it really clear which ones are related.

@riumequa ah yes, putting in the percentage would be a nice touch. My current setup is as follows:

  1. Check pairs for percent relationship
  2. If the relationship is equal to the maximum found percent relation, I encapsulated the pair in to an array and then pushed it into closeStrands array. => closeStrands.push( [batch[i], batch[j]] )
  3. If the relationship is higher than the max, I cleared the closeStrands array and then pushed the encapsulated pair into closeStrands array.

For my step 3, I just didn’t know how to efficiently clear the array, so I just reassigned a blank one instead.

I actually missed the [] around the batch[i], batch[j], thinking you just pushed both into the closeStrands array by their own. Now seeing it again you already did what i suggested in my last sentence :slight_smile:

@riumequa Yeah. It does look like it can be missed easily. I might have to go over some guidelines(if there’s any) regarding whitespaces on each line of code, for readability.

// 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 = (num, arr) => { return { specimenNum: num, dna: arr, mutate(){ let randomBase = returnRandBase(); //selecting a random base let i = Math.floor(Math.random() * 15); //selecting a random number to be used as an index while (randomBase === this.dna[i]){ randomBase = returnRandBase(); } //console.log(this.dna); this.dna[i] = randomBase; return this.dna; }, compareDNA(obj){ let specimen1 = this.specimenNum; let specimen2 = obj.specimenNum; let inCommonCount = 0; let k = 0; let percentageCommonCount; for (let i = 0; i < this.dna.length; i++){ //Iterating through current dna base if (this.dna[i] === obj.dna[k]){ inCommonCount++; } k++; //increasing the count for the passed in dna base } percentageCommonCount = Math.floor((inCommonCount / 15) * 100); //Calculating the percentage of common dna bases between both organisms console.log(`Specimen #${specimen1} and Specimen #${specimen2} have ${percentageCommonCount}% DNA in common`) //console.log(this.dna.length, obj.dna.length) //console.log(inCommonCount); //console.log(this.dna, obj.dna); }, willLikelySurvive(){ let baseCount = 0; let cArray = []; let gArray = []; for (let i = 0; i < this.dna.length; i++){ //Iterating through current dna base if (this.dna[i] === 'C'){ cArray.push(this.dna[i]); //if 'C' exists it gets pushed to a new array } else if (this.dna[i] === 'G'){ gArray.push(this.dna[i]); //if 'G' exists it gets pushed to a new array } } //console.log(this.dna); //console.log(gArray); //console.log(cArray); if(cArray.length >= 9 || gArray.length >= 9){ //checking to see if length of either arrays return true; //is >= 9 as 9/15 is 60% } else { return false; } } }; }; let pAequorSpecimen = []; let specCount = 1; while (pAequorSpecimen.length <= 30){ let newSpec = pAequorFactory(specCount, mockUpStrand()); if (newSpec.willLikelySurvive()){ pAequorSpecimen.push(newSpec); } specCount++; } console.log(pAequorSpecimen); //console.log(pAequorFactory(4, mockUpStrand()).willLikelySurvive()); //console.log(pAequorFactory(4, mockUpStrand()).compareDNA({specimenNum: 6, dna: mockUpStrand()})); //console.log(pAwquorFactory(4, mockUpStrand())); //console.log(pAwquorFactory(4, mockUpStrand()).mutate());

Hay everyone, so this is my solution to the Mysterious Organism challenge. Was quite tough, im not gonna lie, but super stoked that i got through it and feeling more confident with every step! after looking at the solution, i realised that i should have used different array iterations, other then just for loops, just to make my code look a little cleaner and im sure it wouldve made it more efficient, especially with the last 2 methods. But we live and learn!

Here is my GitHub repo for the project: GitHub - MadhavMenon1007/Credit-Card-Checker: First Codecademy Project with JavaScript

Please give some feedback as to how I can optimise my code.

Hello everyone, super excited here to finish this mini-project. If you have the time, please check out my solution on github and let me know what you think of it. Constructive criticism is very much appreciated. Mini-Projects/Mysterious Organism at main · chibike460/Mini-Projects (github.com)

Thanks - I’ll take a look at that. You’re absolutely right about the loops - I don’t know why I got a bit tied up about that in my head. I’m going to revisit the code and try to refactor it at a later stage to see how I have improved.

Great idea as well regarding more than one close relative - I’m definately going to try and factor that into my code and see what I can come up with.

Thanks for the suggestions!

Hello everyone , can someone explain me why in the sample solution if i use const instead of let ,it doesn’t give any errors back . if an array with const can’t be reassigned . how this works fine? line 2

while (survivingSpecimen.length < 30) {
  let newOrg = pAequorFactory(idCounter, mockUpStrand());     // <---------- 
  if (newOrg.willLikelySurvive()) {
    survivingSpecimen.push(newOrg);
  }
  idCounter++;
}

Here’s my solution, I really enjoyed this project in particular! Any feedback/ improvements are appreciated.

lacurnow / mystery-organism (GitHub)- press ‘expand all’! [Second commit · lacurnow/mystery-organism@da19eac · GitHub]

This is because the newOrg Variable gets out of Scope at the end of each iteration of the while loop. So newOrg ceases to exist briefly between each iteration and gets re-declared after entering the while block.

Note that without this mechanism even let would throw an syntax error as declaring the same variable twice within a block is invalid.

if(x) {
let test = 1;
let test = 2; //Syntax Error is thrown
}

Hi guys in console i am getting this: “Specimen #30 and specimen #undefined have 27% DNA in common.
undefined

2 undefined. One of those days, can’t see why. Can anyone point at whats wrong. Thank you.

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() {

      let mutation = Math.floor(Math.random() * this.dna.length);

      let mutatedBase = returnRandBase();

      while(this.dna[mutation] === mutatedBase) {

        mutatedBase = returnRandBase();

      }

      this.dna[mutation] = mutatedBase;

      return this.dna;

    },

    compareDNA (pAequor) {

      let identicalBases = 0;

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

        if(this.dna[i] === pAequor[i]) {

          identicalBases++;

        }

    }

      let percentage = Math.round(((identicalBases / 15) * 100));

      return console.log(`Specimen #${this.specimenNum} and specimen #${pAequor.specimenNum} have ${percentage}% DNA in common.`);

  }

}

}

const test = pAequorFactory(30, mockUpStrand());

console.log(test.compareDNA(mockUpStrand()));

The first undefined comes from accessing pAequor.specimenNum on an DNA Strand array. Note that mockUpStrand() does not return a pAequor. It does return only a DNA strand.

The way the for loop in your compareDNA method is written suggests that the input should indeed be only a DNA strand. But the variable name of the Method suggests that it should be a pAequor. I would suggest rewriting the method such that a pAequor is the required input. Then you can access pAequor.specimenNum in your console.log statement.

In the for loop and if clause, replace pAequor with pAequor.dna

The second undefined comes from returning the console.log() return value in your compareDNA method. Console.log() does not return any value, hence undefined.

// 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, array) => {
  return {
  specimenNum: number,
  dna: array,
  mutate() {
    const index = Math.floor(Math.random() * this.dna.length);
    let oldBase = this.dna[index];
    let newBase = returnRandBase();
    if (oldBase === newBase) {
      return returnRandBase;
      }
      this.dna[index] = newBase
      return this.dna;
    },
    compareDNA(object) {
      let count = 0;
      for (let i = 0; i < (this.dna).length; i ++){
        if (this.dna[index] === this.object[index]) {
          count += 1
      }
    }
  },
  willLikelySurvive() {
    const cAndG = this.dna.filter(dnaBase => dnaBase === 'C' || dnaBase === 'G'){
      if (cAndG.length/this.dna.length > 0.6){
        return true;
      } else {
        return false;
      }
    }
  }
}

let newArray = [];
let i = 0;
if (newArray.length < 30){
  let arr = pAequorFactory(i, mockUpStrand()){
    if (arr.willLikelySurvive() === true) {
      newArray.push(arr);
      i += 1
    }
  }
}










Hi

I was wondering if anyone could help me with my code. I don’t know problems it is that I’m running into.

Thanks Calvin

Skipped this challenge found the wording off putting and confusing just couldn’t get into it

1 Like