Project: DNA Mutation Simulator
mysteriousOrganism.js
Preface: As of the time of this post, I am a new developer, immersing myself in anything and everything JavaScript.
The Project
This code [Github]--completed today--is the end result of a guided project on the "Full Stack Engineer" path on Codecademy.
Project Description
Context: You’re part of a research team that has found a new mysterious organism at the bottom of the ocean near hydrothermal vents. Your team names the organism, Pila aequor (P. aequor), and finds that it is only comprised of 15 DNA bases. The small DNA samples and frequency at which it mutates due to the hydrothermal vents make P. aequor an interesting specimen to study. However, P. aequor cannot survive above sea level and locating P. aequor in the deep sea is difficult and expensive. Your job is to create objects that simulate the DNA of P. aequor for your research team to study.
Notes
I had a lot of fun, though I am a bit of a perfectionist.
While the code actually worked a number of days before I published this post, I later realized that I misinterpreted some of the instructions, namely the "generate 30 viable [read: not variable] instances" part. I then had to re-write and refactor a lot of the methods and, later, some of the functions I built outside of the Object.
Object Lookup
One thing I wanted to accomplish in key areas (and did) was not using if ... else
or switch
. Instead I used objects--a technique or option that I think is the most readable relative to the former two options.
Mutate
As to the .mutate()
method, I also wanted to swap out a random base--at a random point--in the given strand.
I found a resource on the internet that let me accomplish that.
The "swap out random base with one of the other three" piece can be solved in a simpler way, but it just swaps out the first instance of the randomly chosen base. Usually this point was pretty early on in the given strand--no later than say the 5th index.
mutateDNA() {
let mutateBase = {
A: {
1: 'T',
2: 'C',
3: 'G'
},
T: {
1: 'A',
2: 'C',
3: 'G'
},
C: {
1: 'A',
2: 'T',
3: 'G'
},
G: {
1: 'A',
2: 'T',
3: 'C'
}
}
let i = Math.floor(Math.random() * 3) + 1;
let j = Math.floor(Math.random() * this.dna.length);
// https://tinyurl.com/4zkfdfw6
String.prototype.replaceAt = function(index, replacement) {
return this.substring(0, index) +
replacement +
this.substring(index + 1);
}
let originStrand = this.dna;
let randOriginBase = originStrand[j];
let randMutateBase = mutateBase[randOriginBase][i];
let mutatedStrand = originStrand.replaceAt(j, randMutateBase);
return mutatedStrand;
},
Viable Instances
Going back to the "30 viable instances" problem, I also wanted to have a list of viable specimens, but only such that their specimenNum
was not sequential (i.e. NOT 1, 2, 3, ...
).
I accomplished this, but my solution requires first generating a large number specimens, viable or not, then (in a separate function) filtering it to the 30 viable specimens. This means the specimenNum
s are in ascending order, but any non-viable specimen will not appear on the list (i.e. thespecimenNum
s could appear as, for example, 3, 7, 14, 16, ...
)
I doubt my solution to this problem is the best one, and I'm sure there are much more elegant and/or speedier solutions.
Other Stuff
I also built in some options in some of the methods to allow for a sentence (rather than just a strand
, or a number). The way I implemented this may need some tweaking, as they can produce errors, but they have a built in defaults that produce the results that I believe the project is seeking.
I also did not care for displaying the strands as arrays. Each strand is instead a string, e.g. AGTCGGG ...
. Of course a very simple solution was used.
Lastly, I built in some fun console.log
stuff.
I think this is in a pretty good place now overall, and I am happy with the final result.