Mystery organism - member function doesn't return mutated array

The line before the loop should be inside. Drop the let i = 1; line.

const specimenArray = []
for (let i = 0; i < 30; i++) {
  const specimen = new pAequorFactory(i + 1, mockUpStrand());
  if (specimen.willLikelySurvive()) {
    specimenArray.push(specimen);
  }
}

Noted! Thanks for the feedback, I’ve made the change. After running the code again, the output was only 10 specimens instead of 30 - do you have any idea what could have caused this?

Thanks!
Megan

1 Like

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.

const batch = function (instances=30) {
  const pq=[]
  let i = 1
  while (pq.length < instances) {
    const mu = mockUpStrand()
    const nu = pAequorFactory(i, mu)
    if (nu.willLikelySurvive()) {
      pq.push(mu);
      i++;
    }
  }
  return pq
}

That’s what I found in my lesson code. It returns an array so be sure to assign it, or at least log it out.

 console.log(batch())

The optional argument is number of specimen datum we wish to return…

kBatch = batch(1000)

Note that I’m not pushing instances onto the array, but strands, only. Our data doesn’t need to be anything more than raw data, not class instances with their own inherited methods, and such. This is a distinction to be kept aware of when designing code.

I just ran the code that I sent to you a couple emails ago

Yes, that code only draws 30 specimens, not 30 survivors. Examine the latest sample, above for how to draw 30 (or any number of) survivors.

I felt it relevant as an example, and one for future consideration.

So now the choice is yours whether to tackle the extra challenges. It’s your option. Should you accept the challenge, we’re here to bounce your ideas off of.

One would also caution to keep using your own code and only learn from the examples. If you’re learning and can explain the code, then go ahead and fashion your model after it. Keep your intuitions sharp and never stop digging for more concise ways to give instructions to the interpreter. The sharper your intuitions, the simpler will be your logic and your code will read like a book.

As there is no personal information and this thread has reached its denouement, I’m going to share it with the forum by making it a public topic. Others will benefit from your questions and this discourse.

Hi Roy,

I have a quick question about the use of brackets! In the example below, which is solution code for the mystery organism project, brackets are used to refer to a variable within a method within an object on the line that reads “while (this.dna[randBase] === …”. I don’t understand why brackets are used here rather than dot notation. Would dot notation have worked as well? Are you able to provide any insight?

Thanks!

Megan

const pAequorFactory = (specimanNum, dna) => {
return {
specimanNum,
dna,
mutate() {
const randIndex = Math.floor(Math.random() * this.dna.length);
let newBase = returnRandBase();
while (this.dna[randIndex] === newBase) {
newBase = returnRandBase();
}
this.dna[randIndex] = newBase;
return this.dna;
}

randIndex is a variable we are using to access an element by the index given by the variable.

Not for accessing an array. The indices are virtual so we always use subscript notation.

array[index]

Not only are they virtual, they are numbers and numbers cannot be used in dot notation.

Aside

Even while that might be the proposed solution it is a trivial use of arrow function syntax. In this case I would strongly recommend using standard function form. It is more readable and recognizable. Using an arrow function just for the sake of using it means no thought went into this and the writer is guided by novelty rather than reason.

Ah okay, so it’s treated like any other index being accessed! Makes sense, thank you.

I have another question - in the “console.log” line at the end of this code block, I’m confused as to how the “specimenNum” key allows for an output that says “Strand 1 and strand 2 have 33% DNA in common.” How is specimenNum getting these numbers, 1 and 2?

const pAequorFactory = (specimenNum, dna) => {
return {
specimenNum,
dna,
mutate() {
const randBase = Math.floor(Math.random() * this.dna.length);
let oldBase = this.dna[randBase];
let newBase = returnRandBase();
do {
newBase = returnRandBase();
} while (newBase === oldBase);
oldBase = newBase;
return this.dna;
},

compareDNA(pAequorObj) {
let inCommon = 0;
for (let i = 0; i < 15; i++) {
if (this.dna[i] === pAequorObj.dna[i]) {
inCommon++
}
}
inCommon /= 15
inCommon *= 100
console.log(Strand ${this.specimenNum} and strand ${pAequorObj.specimenNum} have ${Math.floor(inCommon)}% DNA in common.);
}
}

output:

Strand 1 and strand 2 have 33% DNA in common.

1 Like

We supply the strand number when we invoke the factory.

Okay, so the factory function supplied the number?

Which we supplied it.

Oh right! Okay thank you :slight_smile:

I have another question if you’d be willing to assist. I’ve been tinkering with the .willLikelySurvive() method in this Mysterious Organisms project to make sure I understand it, but when I test it, it seems as though it may not be working due to the output. Are you able to see where I’ve gone wrong? I’ll paste the code and output below:

willLikelySurvive() {
count = 0;
for (let j of this.dna) {
if (this.dna[j] === ‘C’ || this.dna[j] === ‘G’) count++;
}
const survivalPercentage = ((count / this.dna.length) * 100).toFixed(2);
if (survivalPercentage >= 60) {
console.log(This strand has a greater chance of survival. Percentage of C and G bases is ${survivalPercentage}%);
} else {
console.log(This strand has a lesser chance of survival. Percentage of C and G bases is ${survivalPercentage}%);
}
}
}
}
//test it!
strand = mockUpStrand()
survivalStrand = pAequorFactory(1, strand)
console.log(survivalStrand.willLikelySurvive());

output:

This strand has a lesser chance of survival. Percentage of C and G bases is 0.00%
undefined

Thanks,
Megan

We have no need to compute the percentage, since it is moot. 9 is 60% of 15 so all we need do is determine if count is greater than 8.

Also, we can treat ‘C’ and ‘G’ as one (which is close to what your if statement does). By this point we should have covered the unit on iterators…

for (let x of this.dna) {
    if ('CG'.includes(x)) {

    }
}

The percentage chance of survival is inconsequential. ‘willSurvive’ is the only question that needs answering. Yes, or no.

Good point! I guess there’s no need to overcomplicate things. Okay so I’ve adjusted my code to simply determine whether the likelihood is greater than 8 or not, but after testing it a bunch, I kept on getting “false” and no "true"s. It made me wonder if the method was working properly, so I temporarily adjusted the “8” down to “1” expecting to have an easier time getting a “true” output, but that wasn’t the case. The output is consistently “false.” Do you know why I’m not getting any “true” outputs? Or do you know of a better way I could test my method?

Thanks!

Please post your current willSurvive() method.

You do know that j is not an index? It is the value. Hence we could write it as in the example above.

Here is my current willLikelySurvive() method. It gives me false every time, even if I reduce the 8 to a 1 so I’m not sure how else to test it:

willLikelySurvive() {
count = 0;
for (let j of this.dna) {
if (this.dna[j] === ‘C’ || this.dna[j] === ‘G’) count++;
}
return count > 8
}

That’s the line that needs fixing. j is not an index. It is the value. Just use j. Check the example above.

Also, don’t be fancy with the if statement. Use the code block.

if (...) {
    count++;
}

The relaxed syntax is more for return or break, not repeated code.

Go back to the earlier example and take some ideas from that…

Mystery organism - member function doesn't return mutated array - #23 by mtf