Trying to optimize nested loops

Just doing some generic experiments, related to this challenge

Have this little example:

// To get array of all possible multiplications of i and j, without repeating results
// for i = 1, 2, 3
// for j = 1, 2, 3
let allMults = [];
for (let i = 1; i < 4; i++) {
  for (let j = 1; j < 4; j++) {
    if (allMults.includes(i*j) == false) {
      allMults.push(i*j);
    }
  }
}

console.log(allMults);//[ 1, 2, 3, 4, 6, 9 ]

But I have a suspicion that there should be more elegant approach than nested loops, although struggling to express my thoughts properly, I just see that math here is so… simmetrical i guess.
Interested in general case where sequences of numbers i and j are identical.

Also have a question about code structure.

In solution above I have:

    if (allMults.includes(i*j) == false) {
      allMults.push(i*j);

What if I instead do something like this:

    let oneMult = i * j;
    if (allMults.includes(oneMult) == false) {
      allMults.push(oneMult);

Would it be the better option? I understand this as tradeoff ‘declare one variable to get one multiplication instead of two.’

You can use a set, includes is an extra loop, making your algorithm do an extra nested loop

Thanks for your suggestion.
I think I’ve never used set before. This link to MDN is relevant to your advice? If no, would you be so kind to provide some useful links?
UPDATE: I believe I found what I need on MDN, thanks again!

It really is not necessary to store all the products in an array, set or object. As you are iterating through the nested for loops, you just need to know if the current product created is first a palindrome and second if it larger than the largest one found so far. If it is larger than the largest so far found, then you make the current one the largest. Once all iterations are complete, you simply return the largest you found.

Yeah, for the purpose of the challenge your advice is great!

If I’ll try to get more abstract conclusion from it:

If I need to get final result as integer

I don’t need to store any temporary results in more complex data structures

I need just to store temporary result as integer.

However, I am wondering about process of generating temporary results.
Below, all possible multiplications for i = 1, 2, 3 and identical sequence of numbers j

1 2 3
1 1 2 3
2 2 4 6
3 3 6 9

As we see, central diagonal (1, 4 ,9) - it’s quadratic numbers.
All multiplications above central diagonal which are(2, 3, 6) are identical
to multiplications below central diagonal which are also (2, 3, 6).

So I believe, if I see such mathematical pattern, I can optimize method of generating multiplications.
Now I am doing:

for (let i = 1; i < 4; i++) {
  for (let j = 1; j < 4; j++) {
    tempResult = i*j;
  }
}

So my issue is - could I apply mathematical patterns from the table above to my solution and make something more efficient than this two nested loops?

I am not sure what knowledge/skills I need to acquire to move in such direction?

What do you mean by central diagonal(2, 3, 6)?

I mean all results above central diagonal. Central diagonal is (1,4 ,9).
All results above it is (2,3,6)

I am not sure how the diagonals would help you here. You still need to check the product to see if the product is a palindrome and not whether or not the diagonals are palindromes. Maybe I am missing something you are seeing here.

Right now I am not concerned about check for palindrome.

Before I will check ‘if number is palindrome’, I need to generate that number.
In example above I have nested loops, these loops will generate 9 results total.

If I take a close look at this results: (2,3,6,1,4,9,2,3,6)
I see mathematical pattern. See which results are repeating? There may be the way to use this pattern in actual code.

I wanna to come up with implementation which will allow to reduce number of checks in the first place.

If my explanation is still not clear, I will implement solution of the actual challenge, will comment it properly, and will express my logic in that context.

Instead of let j = 1 try let j = i

1 Like

That actually was it! I believe this approach is scalable and will work when applied to actual challenge.
Do you have any advice for me to get better when trying to optimize something like this?

Just keep practicing! Now you have this trick in your toolbelt.