0

Given the following code to find Pythagorean Triples, why am I getting duplicates rather than excluding them with the While loop followed by the If condition?

var a, b, c, i, pyTrips, temp;
pyTrips = new Array();
temp = new Array();

for (a = 1; a <= 10; a++) {
    for (b = 1; b <= 10; b++) {
        with (Math) {
            c = sqrt(pow(a, 2) + pow(b, 2));
        }
        if (c % 1 == 0) {
            temp = a < b ? [a, b, c] : [b, a, c];
            i = 0;
            while (i < pyTrips.length && pyTrips[i] !== temp) {
                i++;
            }
            if (i === pyTrips.length) {
                pyTrips.push(temp);
            }
            console.log(pyTrips.toString());
        }
    }
}

I assume it's the pyTrips[i]!==temp part that's tripping things up, but I've checked and there's no type casting or anything; the comparison is in fact between two arrays. So not sure why the While loop seems to make it to pyTrips.length every time.

Abito Prakash
  • 4,368
  • 2
  • 13
  • 26
DKqwerty
  • 15
  • 5
  • `[1] !== [1]`. See [this](https://stackoverflow.com/questions/7837456/how-to-compare-arrays-in-javascript), or any of the many other questions about object and array equality. Also, there's no need for `with`, which isn't available in strict mode and is dangerous (you can do `const { pow, sqrt } = Math` if you want to use those functions the same way). – Zac Anger Aug 09 '23 at 04:57
  • Thanks for the link: it's very hard to track down these answers when they involve such generic terms (read as: mostly irrelevant results). I'm using this script locally to just dump info: it will never be run in strict mode. And I'm using With just to clean up the line's readability, nothing more. – DKqwerty Aug 09 '23 at 05:27

3 Answers3

2

Javascript arrays are objects. Objects are compared by comparing their object references, NOT by comparing their contents.

You can do this by using toString on both arrays:

while(i<pyTrips.length && pyTrips[i].toString()!==temp.toString()){ i++; }
Tim Roberts
  • 48,973
  • 4
  • 21
  • 30
1

Your assumption is correct, you cannot compare two arrays directly. When you compare two arrays using the === operator, it compares their references, not their content.

One hacky way to solve this is to use toString(), convert the two arrays to string and then compare

pyTrips[i].toString() !== temp.toString()

Another way is to use a utility function which compares arrays

const isEqualArr = (arr1, arr2) => {
    if (arr1.length !== arr2.length) {
        return false;
    }

    return arr1.every((ele, index) => ele === arr2[index]);
};

And then use it like

!isEqualArr(pyTrips[i], temp)
Abito Prakash
  • 4,368
  • 2
  • 13
  • 26
  • Understood, thanks for the help! – DKqwerty Aug 09 '23 at 05:36
  • Am I really supposed to format my code on _Stack_ the way you changed it? I can deal with the extra whitespace, but I hate to put statements containing only a single line on multiple lines. – DKqwerty Aug 09 '23 at 05:43
  • I just used an online prettifier, https://prettier.io/playground/#. In my humble opinion, it improves readability. – Abito Prakash Aug 09 '23 at 05:51
1

You can try clearing the array after each successful iteration:

var a, b, c, i, pyTrips, temp;
pyTrips = new Array();
temp = new Array();

for (a = 1; a <= 10; a++) {
    for (b = 1; b <= 10; b++) {
        with (Math) {
            c = sqrt(pow(a, 2) + pow(b, 2));
        }
        if (c % 1 == 0) {
            temp = a < b ? [a, b, c] : [b, a, c];
            i = 0;
            while (i < pyTrips.length && pyTrips[i] !== temp) {
                i++;
            }
            if (i === pyTrips.length) {
                pyTrips.push(temp);
            }
            console.log(pyTrips.toString());
            pyTrips = [];
        }
    }
}
Venkatesh K
  • 4,364
  • 4
  • 18
  • 26