Mysterious Organism (Javascript)

Hello all, my name is Mike and this is my first forum post. I’ve been doing alright on this project and going through forums to find help to move forward. I cant seem to figure out why I’m getting an infinite loop of booleans when I try to call createDNAStrands(). My willLikelySurvive() seems to work fine as well as all the code prior to createDNAStrands(). Looking at other forum posts it looks as if my createDNAStrands code is accurate, so it seems the problem has to be occurring somewhere else.

The link to the project is here: https://www.codecademy.com/paths/front-end-engineer-career-path/tracks/fecp-22-javascript-syntax-part-ii/modules/wdcp-22-mysterious-organism/projects/mysterious-organism

My code is:

// 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
};

// factory function
const pAequorFactory = (num, arr) => {
  return pAequor = {
    _speciNum: num,
    _dna: arr, 

    mutate() {
      let randBase = returnRandBase();
      let newBaseIndex = Math.floor(Math.random() * 15);
      let baseToMutate = this._dna[newBaseIndex];
      randBase !== baseToMutate ? this._dna.splice(newBaseIndex, 1, randBase) : this.mutate();
    },  

    compareDNA(altDNA) {
      let numOfSim = 0;
      let pA1 = this._dna;
      let pA2 = altDNA._dna;
      for (i = 0; i < 15; i++) {
        for (j = 0; j < 15; j++) {
          if (pA1[i] === pA2[j] && i === j){
          numOfSim++;
          }
        }
      }
      let percentSame = (numOfSim / pA2.length) * 100;
      console.log(`Sample 1 and sample 2 have ${percentSame.toFixed(1)}% in common.`);
    },

    willLikelySurvive() {
      let percentDNA = 0;
      for (i = 0; i < 15; i++){
        if (this._dna[i] === 'C' || this._dna[i] === 'G'){
          percentDNA++;
        }
      }
      (percentDNA / this._dna.length) * 100 >= 60 ?  console.log(true) : console.log(false);
    }
  }
};

// create 30 survivors   
const createDNAStrands = num => {
  let superiorDNA = [];
  while (superiorDNA.length < num){
    let lastSpeciNum = superiorDNA.length;
    let newSpecimen = pAequorFactory(lastSpeciNum++, mockUpStrand());  
    if (newSpecimen.willLikelySurvive()){
      superiorDNA.push(newSpecimen);  
    }  
  } 
  return superiorDNA;
};     
// tests 
const dna1 = pAequorFactory(1, mockUpStrand());
const dna2 = pAequorFactory(2, mockUpStrand());

//createDNAStrands(30);
console.log(dna1._dna);
dna1.compareDNA(dna2);
dna1.willLikelySurvive();


Hi,
I don’t know how you call createDNAStrands(), probably with the argument 30 for the parameter num? Since you don’t count down num, the condition superiorDNA.length < num is always fulfilled.

So a for loop would be the better option, I think.

Hey Mirja, thanks for your response! Changing the loop to a for loop definitely fixed the infinity problem. It’s interesting, I saw a working code that used the while loop exactly as I did except num was the parameter and they put DNA.length < 30. Seemed it would limit the function to 30 even if you put 50 in the parameter. Somehow theirs worked, but I think you’re correct as the for loop has more control.

Oh ok. Just checked again. It should work with a while loop. If it doesn’t that means that the push doesn’t work and the superiorDNA array stays empty. So superiorDNA.length is 0 all the time. That means that if (newSpecimen.willLikelySurvive())apparently is never true.
If you run your while loop with a break and log the result of newSpecimen.willLikelySurvive(), you’ll see why it’s never true:

let counter = 0;
while (superiorDNA.length < num){
    let lastSpeciNum = superiorDNA.length;
    let newSpecimen = pAequorFactory(lastSpeciNum++, mockUpStrand());  
    let willSurvive = newSpecimen.willLikelySurvive();
    if (willSurvive){
      superiorDNA.push(newSpecimen);  
    }  
    console.log(counter, willSurvive)
    counter++
    if(counter===30) {
      break;
    }
  } 

I’m pretty sure after reading a lot more it has to be a while loop. Even if .push was working it would only run “num” times and not keep running until it pushed the “num” of survivors.

Posted my mtf:
“What code did you use to draw all the specimens and test them? The simple answer would be that of 30 generated strains only 10 made the cut. To get 30 strains that all make the grade then we need more logic than a for loop.”

Let me test your code now.

Hmmm, seems its returning the boolean value above the log but returning undefined inside the willSurvive

In your willLikelySurvive method you do not return anything. That’s why newSpecimen.willLikelySurvive(); is always undefined.

So then the problem is in the willLikelySurvive() code. Or perhaps it’s because I should be running it on mockUpStrand(). Calling dna1.willLikelySurvive(), for instance, comes back as a boolean and not undefined, which is why I thought willLikelySurvive() was working.

The problem is that this line does nothing else than logging. But these bools are what you need in the loop. So you need to return them rather than logging them.

Ok I fixed the problem there by:

willLikelySurvive() {
      let percentDNA = 0;
      for (let i of this._dna) {
        if (this._dna[i] === 'C' || this._dna[i] === 'G'){
          percentDNA++;
        }
      }
      return percentDNA > 8
    }
  }
};

Nothing is undefined now. Thanks so much for your help! This was definitely a test for me.

1 Like

Hello everyone! I just wanted to update my completed code for others who are stuck like I was.

// 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
};

// factory function
const pAequorFactory = (num, arr) => {
  return pAequor = {
    _speciNum: num,
    _dna: arr, 
//mutate function
    mutate() {
      let randBase = returnRandBase();
      let newBaseIndex = Math.floor(Math.random() * 15);
      let baseToMutate = this._dna[newBaseIndex];
      randBase !== baseToMutate ? this._dna.splice(newBaseIndex, 1, randBase) : this.mutate();
      return this._dna;
    },  
 //compare function 
    compareDNA(altDNA) {
      let numOfSim = 0;
      let pA1 = this._dna;
      let pA2 = altDNA._dna;
      for (i = 0; i < 15; i++) {
        for (j = 0; j < 15; j++) {
          if (pA1[i] === pA2[j] && i === j){
          numOfSim++;
          }
        }
      }
      let percentSame = (numOfSim / pA2.length) * 100;
      console.log(`Sample 1 and sample 2 have ${percentSame.toFixed(1)}% in common.`);
    },
//will survive function
    willLikelySurvive() {
      let percentDNA = 0;
      for (let i of this._dna) {
        if ('CG'.includes(i)){
          percentDNA++;
        }
      }
      return percentDNA > 8
    },
//complementary strand function
    complementStrand() {
      let compStrand = [];
      for(let i = 0; i < this._dna.length; i++) {
        switch (this._dna[i]) {
          case 'A':
            compStrand[i] = 'T';
          break;
          case 'T':
            compStrand[i] = 'A';
          break;
          case 'C':
            compStrand[i] = 'G';
          break;
          case 'G':
            compStrand[i] = 'C';
          break;
        }
      }
      return compStrand;
    }
  }
};

// create 30 survivors   
const createDNAStrands = num => {
  const superiorDNA = [];
  let i = 1;
  while (superiorDNA.length < num){
    let mu = mockUpStrand();
    let newSpecimen = pAequorFactory(i, mu);  
    let willSurvive = newSpecimen.willLikelySurvive();
    if (willSurvive) {
      superiorDNA.push(i, mu); 
    }
    i++    
  }
  return superiorDNA; 
};   



const dna1 = pAequorFactory(1, mockUpStrand());
const dna2 = pAequorFactory(2, mockUpStrand());
//Uncomment the different tests to try it out
/* double the num of strands you create because I included strand number in array and it is counted as 1 */
//console.log(createDNAStrands(60))  
//console.log(dna1._dna);
//console.log(dna1.mutate())
//dna1.compareDNA(dna2);
//console.log(dna1.willLikelySurvive())
//console.log(dna1.complementStrand())

Hope it helps. Happy coding!