Nested for loops -- can the counter for one loop reference the other?

Referencing the extra project in Mysterious Organisms, where you’re asked to find the two most related organisms in a sample group (array) of organisms, for i<sampleArray.length, I would like to compare the DNA of object at sampleArray[i]
with the DNA of every object in sampleArray with an index greater than i.

This would run through every combination (i, j) in the sampleArray without repeating any unnecessary calculations (so if it’s already run through (i, j), it doesn’t repeat the calculation with (j, i)), but it’s freezing the codeacademy evaluator thing, so I’m guessing you’re not allowed to do this?

Code below:

const mostRelated = (sampleArray) => {
  let currentMax = 0;
  let currentMost = [];
  for (i=0; i<sampleArray.length; i++) {
    for (j=i+1; j<sampleArray.length; j++) {
      let ijPercentage = sampleArray[i].compareDNA(sampleArray[j]);
      if (ijPercentage > currentMax) {
        currentMax = ijPercentage;
        currentMost = [sampleArray[i], sampleArray[j]];
      }
    }
  }
  return `Sample ${currentMost[0].id} and Sample ${currentMost[1].id} are the most related organisms in the sample, with ${currentMax}% DNA in common.`;
};

I suspect this is not something that works, but I don’t know why, or what other construction one might use to get the same effect.

Does anyone know why you can’t do this (initialize j to i+1), and know how else to achieve the same effect without unnecessarily duplicating calculations?

Hello @css2055428083, welcome to the forums! You can do this. Running:

for (let i = 0; i<3; i++){
    for (let j=i+1; j<3; j++){
    console.log(j);
    }
} 

gives the output:

1
2
2

When I run your code, I get a compareDNA is not a function-is it declared elsewhere in the code? Also, make sure you don’t have any infinite loops in your code.

it is declared elsewhere (and worked with tests), but it’s super helpful to know this is in fact something one can do. I don’t see any obvious infinite loops, but now I know I should keep hunting. Thanks :slight_smile:

and if anyone sees any infinite loops in this code, please let me know!

1 Like

Can you post your full code, please?

Sure, and thanks for taking a look!

// 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 = (id, dnaStrand) => {
  return {
    id: id,
    dnaStrand: dnaStrand,
    mutate() {
      let baseIndex = Math.floor(Math.random())*15;
      let newBase = returnRandBase();
      if (this.dnaStrand[baseIndex] === newBase) {
        this.mutate();
      } else {
        this.dnaStrand[baseIndex] = newBase;
      }
    },
    compareDNA(otherPA) {
      let counter = 0;
      for (i=0; i<15; i++) {
        if (this.dnaStrand[i] === otherPA.dnaStrand[i]) {
          counter++;
        }
      }
      let percentage = 100*counter/15;
      console.log(`Specimen #${this.id} shares ${percentage}% DNA with specimen #${otherPA.id}`);
      return percentage;
    },
    willLikelySurvive() {
      let counter = 0;
      for (i=0; i<15; i++) {
        if (this.dnaStrand[i] === "G" || this.dnaStrand[i]==="C") {
          counter++
        }
      }
      if (100*counter/15 >= 60) {
        return true;
      } else {
        return false;
      }
    },
    complementStrand() {
      const dnaArray = ["A", "T", "C", "G"];
      const complArray = ["T", "A", "G", "C"];
      const complementStrand = [];
      for (i=0; i<this.dnaStrand.length; i++) {
        let j = dnaArray.indexOf(this.dnaStrand[i]);
        complementStrand.push(complArray[j]);
      }
      return complementStrand;
    }
  };
};

let make30SurvivalArray = (idMultiple) => {
  const SampleArray = [];
  for (i=1; i<31; i++) {
    let iSample = pAequorFactory(i*idMultiple, mockUpStrand());
    SampleArray.push(iSample);
  }
  return SampleArray;
};

const mostRelated = (sampleArray) => {
  let currentMax = 0;
  let currentMost = [];
  for (i=0; i<sampleArray.length; i++) {
    for (j=i+1; j<sampleArray.length; j++) {
      let ijPercentage = sampleArray[i].compareDNA(sampleArray[j]);
      if (ijPercentage > currentMax) {
        currentMax = ijPercentage;
        currentMost = [sampleArray[i], sampleArray[j]];
      }
    }
  }
  console.log(`Sample ${currentMost[0].id} and Sample ${currentMost[1].id} are the most related organisms in the sample, with ${currentMax}% DNA in common.`);
};

let mostRelatedTestSample = make30SurvivalArray(1);
mostRelated(mostRelatedTestSample);

What is the expected output? When I run this code off-platform, I get the following results:

Specimen #1 shares 20% DNA with specimen #2
Specimen #16 shares 33.333333333333336% DNA with specimen #3
Specimen #16 shares 26.666666666666668% DNA with specimen #4
…(and more)

Try refreshing the browser, or using chrome if you’re using a different browser.

oh wait, so it’s returning the string, not the percentage? even though the final line in the compareDNA method is

return percentage;

that seems totally possible, I’m sort of just making this up as I go along. I’m not sure how else to get it to print a string that tells me what the result is and then also returns the actual number so I can use it in other functions…

oh I’m sorry, I forgot to comment on your suggestion – I had refreshed the browser a few times (Safari), but I haven’t tried chrome yet. will do

It prints it to the console because you have a console.log() just before the return statement:

This gets printed every time the function is called.

ah I think I wasn’t clear. I put the console.log() there for this reason; I wanted the function to tell me what the result was, and THEN return the actual percentage (as in return percentage; on the last line) so that I could use it in the comparison function to determine which pair was most related. I thought you were saying that the problem with the original code was that it was getting stuck on the console.log(), and therefore not able to use the results of compareDNA in a numerical comparison, as in mostRelated.