Mysterious Organism | Step 4

Hello,

I have been working on Step 4 of the Mysterious Organism exercise and I feel I am 90% of the way to completing this step but there is a small problem I am encountering.

Every time I call the function, 1 in every 5-7 calls, the console logs the same array. I think somewhere in my conditional I have omitted something but I can not figure out what. Any hints or tips are appreciated.

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

// Answer starts here
const pAequorFactory = (specimenNum, dna) => {
  return {
    specimenNum,
    dna,
    mutate() {
      console.log(this.dna)
      const mutatedBase = Math.floor(Math.random() * this.dna.length)
      if (returnRandBase() == mutatedBase) {
        returnRandBase()
      } else if (returnRandBase() != mutatedBase) {
        this.dna[mutatedBase] = returnRandBase()
      }
      return this.dna
    }
  }
}

console.log(pAequorFactory(1, mockUpStrand()).mutate())

I have logged the original dna property to compare and that is how I know that the 2 arrays are matching up every few calls.

Some thoughts I am toying around with is using the splice method to insert the random base into the dna array, but I am not entirely sure if that would fix the problem.

I have also reordered (i.e. reversed the 2 if statements) the conditionals and it either makes the problem worse (i.e. the mutated array matches the original more often) or it does not work at all.

This doesn’t look quite right. Can you work that into a loop of some kind?

Also, please post a link to the landing page for this project. Belay, I found the bookmark.

Hey, thanks for the tip.

I tried fiddling with do…while and while loops but I don’t think its the best way to go, so I copied over the dnaBases array and created a for loop. Unfortunately, I am still running into the same problem where every few times I run it, the same arrays are returned.

Here is what I came up with for the loop:

const pAequorFactory = (specimenNum, dna) => {
  return {
    specimenNum,
    dna,
    mutate() {
      console.log(this.dna)
      const mutatedBase = Math.floor(Math.random() * this.dna.length)
      console.log(mutatedBase)
      const dnaBases = ['A', 'T', 'C', 'G']
      for (let i = 0; i < dnaBases.length; i++) {
        if (dnaBases[i] != mutatedBase) {
          console.log(dnaBases[i])
          this.dna[mutatedBase] = dnaBases[i]
          break
        } else if (dnaBases[i] == mutatedBase) {
          continue
        }
      }
      return this.dna
    }
  }
}

I am logging it at every point to see what’s happening. I do have a couple of questions:

  1. When I log mutatedBase it returns a number, could that be why it is not working 100% of the time?
  2. Did I use the continue and break statements correctly? I switched the order of the 2 if statements and I am still running into the same issue.

Thanks for your help!

mutatedBase is supposed to be a number which represents a randomly selected index in the strand. There is nothing to compare it to with any meaning. Using this.dna[mutatedBase] in the comparison is meaningful.

Yes, for the most part. break means we are substituting an explicitly different base. However, continue is meant to carry on until there is no equality, which while an extremely outside chance it would take more than 15 iterations, an outside chance nonetheless. Were that the case, this.dna would remain unchanged. That is why we need a while loop.

That list already exists in the returnRandBase function that we use to randomly return a single base. The above line can be replaced by,

let randBase = returnRandBase()

initialized before the while loop and which can be compared and replaced inside the loop.

This is the roadmap I devised for mutate():

  • generate random index and assign to a const
  • poll the current dna strand at that index and assign to a const
  • returnRandBase() and assign to a let
  • loop with while against the condition of the previous two variables being equal
    • assign new value of returnRandBase() to let declared variable
  • assign most recent let declared value to dna strand at the generated index
  • return dna strand

The function will self-document so the three variables can be single letter. I used x, y, and z for very readable code.

Revised roadmap…

Third bullet point: declare let variable; leave undefined
Fourth bullet point: loop with do…while. The condition remains the same.

const x = ...
const y = ...[x]
let z;
do {
  z = ...()
} while (y == z)
...[x] = z
1 Like
mutate
    mutate () {
      const x = floor(random() * 16)
      const y = this.dna[x]
      let z;
      do {
        z = returnRandBase()
      } while (y === z)
      this.dna[x] = z
      return this.dna
    },

At some point floor and random will have been defined.

const floor = Math.floor
const random = Math.random

Wow, such an interesting problem with little details.

I definitely think I had the right approach, but I need to learn to slow down and break the problem down a bit more. I also definitely need to hammer down my fundamentals because I moved past the option of using while loops too quickly.

You live and you learn.

Thank you for your guidance!

1 Like