Credit Card Checker - Alien arrays

Hi, all. My first time using the forum. Trying to comply with the guidelines, but let me apologize in advance if I’ve failed to do so.

I’m working on item 4 of the Credit Card Checker project. Please find my code and console results below. The code seems to be working fine until the ‘findInvalidCards’ function. When I run it with a console.log, the arrays I get don’t make any sense.

=== My code below the project’s initial code

// All valid credit card numbers
const valid1 = [4, 5, 3, 9, 6, 7, 7, 9, 0, 8, 0, 1, 6, 8, 0, 8];
const valid2 = [5, 5, 3, 5, 7, 6, 6, 7, 6, 8, 7, 5, 1, 4, 3, 9];
const valid3 = [3, 7, 1, 6, 1, 2, 0, 1, 9, 9, 8, 5, 2, 3, 6];
const valid4 = [6, 0, 1, 1, 1, 4, 4, 3, 4, 0, 6, 8, 2, 9, 0, 5];
const valid5 = [4, 5, 3, 9, 4, 0, 4, 9, 6, 7, 8, 6, 9, 6, 6, 6];

// All invalid credit card numbers
const invalid1 = [4, 5, 3, 2, 7, 7, 8, 7, 7, 1, 0, 9, 1, 7, 9, 5];
const invalid2 = [5, 7, 9, 5, 5, 9, 3, 3, 9, 2, 1, 3, 4, 6, 4, 3];
const invalid3 = [3, 7, 5, 7, 9, 6, 0, 8, 4, 4, 5, 9, 9, 1, 4];
const invalid4 = [6, 0, 1, 1, 1, 2, 7, 9, 6, 1, 7, 7, 7, 9, 3, 5];
const invalid5 = [5, 3, 8, 2, 0, 1, 9, 7, 7, 2, 8, 8, 3, 8, 5, 4];

// Can be either valid or invalid
const mystery1 = [3, 4, 4, 8, 0, 1, 9, 6, 8, 3, 0, 5, 4, 1, 4];
const mystery2 = [5, 4, 6, 6, 1, 0, 0, 8, 6, 1, 6, 2, 0, 2, 3, 9];
const mystery3 = [6, 0, 1, 1, 3, 7, 7, 0, 2, 0, 9, 6, 2, 6, 5, 6, 2, 0, 3];
const mystery4 = [4, 9, 2, 9, 8, 7, 7, 1, 6, 9, 2, 1, 7, 0, 9, 3];
const mystery5 = [4, 9, 1, 3, 5, 4, 0, 4, 6, 3, 0, 7, 2, 5, 2, 3];

// An array of all the arrays above
const batch = [valid1, valid2, valid3, valid4, valid5, invalid1, invalid2, invalid3, invalid4, invalid5, mystery1, mystery2, mystery3, mystery4, mystery5];


// Add your functions below:
let validateCred = (arr) => {
  // create the array in reverse
  let cCard = arr.reverse();
  // array that will contain numbers to sum
  let cCard1 = [];
  // iterate through the array to: 
  // 1. double every other digit
  // 2. if the result is >9, do -9
  // 3. push each number to cCard1
  for (let i = 0; i < cCard.length; i++) {
    if (i%2 === 0 /* even index */) {
      cCard1.push(cCard[i]);
    }
    else {
      // take number, *2
      if ((cCard[i] = cCard[i]*2) > 9) {
        cCard[i] = cCard[i] - 9;
        cCard1.push(cCard[i]);
      } else {
        cCard1.push(cCard[i]);
      }
    }
  }

  // sum values in cCard1
  let sumCard1 = cCard1.reduce((a,b)=>a+b);

  // Test module
  if (sumCard1 %10 === 0) {
    return true
  } else {
    return false
  }
}

let invalidCards = [];
let validCards = [];

let findInvalidCards = (nArr) => {
  for (i = 0; i < nArr.length; i++ ) {
    if (validateCred(nArr[i]) === false ) {
      invalidCards.push(nArr[i]);
    } else {
      validCards.push(nArr[i]);
    }
  }
}

findInvalidCards(batch);
console.log(invalidCards);
// console.log(validCards);

===
This is what the terminal looks like when I run:

[ [ 5, 9, 7, 2, 9, 0, 1, 5, 7, 7, 7, 5, 2, 6, 5, 8 ],
[ 3, 8, 6, 8, 3, 2, 2, 9, 3, 6, 9, 1, 5, 9, 7, 1 ],
[ 4, 2, 9, 9, 5, 8, 4, 7, 0, 3, 9, 5, 5, 5, 3 ],
[ 5, 6, 9, 5, 7, 5, 1, 3, 9, 5, 2, 2, 1, 2, 0, 3 ],
[ 4, 1, 8, 6, 8, 7, 2, 5, 7, 9, 1, 0, 2, 7, 3, 1 ],
[ 4, 2, 4, 1, 0, 6, 8, 3, 9, 2, 0, 7, 4, 8, 3 ],
[ 3, 0, 2, 3, 5, 3, 2, 3, 9, 0, 2, 0, 7, 5, 3, 2, 1, 0, 6 ],
[ 3, 9, 0, 5, 1, 4, 9, 3, 1, 5, 7, 7, 9, 4, 9, 8 ] ]

===
No idea where these arrays are coming from. Please, help.

1 Like

reverse()

When called on an array mutates it in place. https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/reverse

2 Likes

Hi - welcome to the forums! :slight_smile:

You’ve formatted your code right, so you’re off to a flying start. :+1:

You’re creating them, in a fashion.

When you’re doing let cCard = arr.reverse();, JS is reversing the array but then putting a reference to the newly reversed array into cCard. It’s not creating a new object.

You can validate this by using the identity comparator ===, like so (lines 30-32):

// All valid credit card numbers
const valid1 = [4, 5, 3, 9, 6, 7, 7, 9, 0, 8, 0, 1, 6, 8, 0, 8];
const valid2 = [5, 5, 3, 5, 7, 6, 6, 7, 6, 8, 7, 5, 1, 4, 3, 9];
const valid3 = [3, 7, 1, 6, 1, 2, 0, 1, 9, 9, 8, 5, 2, 3, 6];
const valid4 = [6, 0, 1, 1, 1, 4, 4, 3, 4, 0, 6, 8, 2, 9, 0, 5];
const valid5 = [4, 5, 3, 9, 4, 0, 4, 9, 6, 7, 8, 6, 9, 6, 6, 6];

// All invalid credit card numbers
const invalid1 = [4, 5, 3, 2, 7, 7, 8, 7, 7, 1, 0, 9, 1, 7, 9, 5];
const invalid2 = [5, 7, 9, 5, 5, 9, 3, 3, 9, 2, 1, 3, 4, 6, 4, 3];
const invalid3 = [3, 7, 5, 7, 9, 6, 0, 8, 4, 4, 5, 9, 9, 1, 4];
const invalid4 = [6, 0, 1, 1, 1, 2, 7, 9, 6, 1, 7, 7, 7, 9, 3, 5];
const invalid5 = [5, 3, 8, 2, 0, 1, 9, 7, 7, 2, 8, 8, 3, 8, 5, 4];

// Can be either valid or invalid
const mystery1 = [3, 4, 4, 8, 0, 1, 9, 6, 8, 3, 0, 5, 4, 1, 4];
const mystery2 = [5, 4, 6, 6, 1, 0, 0, 8, 6, 1, 6, 2, 0, 2, 3, 9];
const mystery3 = [6, 0, 1, 1, 3, 7, 7, 0, 2, 0, 9, 6, 2, 6, 5, 6, 2, 0, 3];
const mystery4 = [4, 9, 2, 9, 8, 7, 7, 1, 6, 9, 2, 1, 7, 0, 9, 3];
const mystery5 = [4, 9, 1, 3, 5, 4, 0, 4, 6, 3, 0, 7, 2, 5, 2, 3];

// An array of all the arrays above
const batch = [valid1, valid2, valid3, valid4, valid5, invalid1, invalid2, invalid3, invalid4, invalid5, mystery1, mystery2, mystery3, mystery4, mystery5];


// Add your functions below:
let validateCred = (arr) => {
    // create the array in reverse
    let cCard = arr.reverse();
    if (cCard === arr) {  // both cCard and arr must reference the same object for this to be true!
      console.log("Debug: Objects have same reference"); // so we might see this on the console...
    }
    // array that will contain numbers to sum
    let cCard1 = [];
    // iterate through the array to: 
    // 1. double every other digit
    // 2. if the result is >9, do -9
    // 3. push each number to cCard1
    for (let i = 0; i < cCard.length; i++) {
        if (i % 2 === 0 /* even index */) {
            cCard1.push(cCard[i]);
        }
        else {
            // take number, *2
            if ((cCard[i] = cCard[i] * 2) > 9) {
                cCard[i] = cCard[i] - 9;
                cCard1.push(cCard[i]);
            } else {
                cCard1.push(cCard[i]);
            }
        }
    }

    // sum values in cCard1
    let sumCard1 = cCard1.reduce((a, b) => a + b);

    // Test module
    if (sumCard1 % 10 === 0) {
        return true
    } else {
        return false
    }
}

let invalidCards = [];
let validCards = [];

let findInvalidCards = (nArr) => {
    for (i = 0; i < nArr.length; i++) {
        if (validateCred(nArr[i]) === false) {
            invalidCards.push(nArr[i]);
        } else {
            validCards.push(nArr[i]);
        }
    }
}

findInvalidCards(batch);
console.log(invalidCards);
// console.log(validCards);

and we see the following come back from the console

Debug: Objects have same reference
Debug: Objects have same reference
Debug: Objects have same reference
Debug: Objects have same reference
Debug: Objects have same reference
Debug: Objects have same reference
Debug: Objects have same reference
Debug: Objects have same reference
Debug: Objects have same reference
Debug: Objects have same reference
Debug: Objects have same reference
Debug: Objects have same reference
Debug: Objects have same reference
Debug: Objects have same reference
Debug: Objects have same reference
[ [ 5, 9, 7, 2, 9, 0, 1, 5, 7, 7, 7, 5, 2, 6, 5, 8 ],
  [ 3, 8, 6, 8, 3, 2, 2, 9, 3, 6, 9, 1, 5, 9, 7, 1 ],
  [ 4, 2, 9, 9, 5, 8, 4, 7, 0, 3, 9, 5, 5, 5, 3 ],
  [ 5, 6, 9, 5, 7, 5, 1, 3, 9, 5, 2, 2, 1, 2, 0, 3 ],
  [ 4, 1, 8, 6, 8, 7, 2, 5, 7, 9, 1, 0, 2, 7, 3, 1 ],
  [ 4, 2, 4, 1, 0, 6, 8, 3, 9, 2, 0, 7, 4, 8, 3 ],
  [ 3, 0, 2, 3, 5, 3, 2, 3, 9, 0, 2, 0, 7, 5, 3, 2, 1, 0, 6 ],
  [ 3, 9, 0, 5, 1, 4, 9, 3, 1, 5, 7, 7, 9, 4, 9, 8 ] ]

Consequently, any operation we perform on cCard also affects the variable passed as arr because both variables are referencing the same object in memory.

This means that when we’re doing things like doubling every other digit, and/or subtracting 9… we’re manipulating the original copy of the card number that we want to validate. These then get pushed, in their reversed-probed-and-prodded form, to the invalidCards array we’re outputting later on. :slight_smile:

We can adjust the code, slightly, to create a clone of the object and then manipulate that (lines 29,30).

// All valid credit card numbers
const valid1 = [4, 5, 3, 9, 6, 7, 7, 9, 0, 8, 0, 1, 6, 8, 0, 8];
const valid2 = [5, 5, 3, 5, 7, 6, 6, 7, 6, 8, 7, 5, 1, 4, 3, 9];
const valid3 = [3, 7, 1, 6, 1, 2, 0, 1, 9, 9, 8, 5, 2, 3, 6];
const valid4 = [6, 0, 1, 1, 1, 4, 4, 3, 4, 0, 6, 8, 2, 9, 0, 5];
const valid5 = [4, 5, 3, 9, 4, 0, 4, 9, 6, 7, 8, 6, 9, 6, 6, 6];

// All invalid credit card numbers
const invalid1 = [4, 5, 3, 2, 7, 7, 8, 7, 7, 1, 0, 9, 1, 7, 9, 5];
const invalid2 = [5, 7, 9, 5, 5, 9, 3, 3, 9, 2, 1, 3, 4, 6, 4, 3];
const invalid3 = [3, 7, 5, 7, 9, 6, 0, 8, 4, 4, 5, 9, 9, 1, 4];
const invalid4 = [6, 0, 1, 1, 1, 2, 7, 9, 6, 1, 7, 7, 7, 9, 3, 5];
const invalid5 = [5, 3, 8, 2, 0, 1, 9, 7, 7, 2, 8, 8, 3, 8, 5, 4];

// Can be either valid or invalid
const mystery1 = [3, 4, 4, 8, 0, 1, 9, 6, 8, 3, 0, 5, 4, 1, 4];
const mystery2 = [5, 4, 6, 6, 1, 0, 0, 8, 6, 1, 6, 2, 0, 2, 3, 9];
const mystery3 = [6, 0, 1, 1, 3, 7, 7, 0, 2, 0, 9, 6, 2, 6, 5, 6, 2, 0, 3];
const mystery4 = [4, 9, 2, 9, 8, 7, 7, 1, 6, 9, 2, 1, 7, 0, 9, 3];
const mystery5 = [4, 9, 1, 3, 5, 4, 0, 4, 6, 3, 0, 7, 2, 5, 2, 3];

// An array of all the arrays above
const batch = [valid1, valid2, valid3, valid4, valid5, invalid1, invalid2, invalid3, invalid4, invalid5, mystery1, mystery2, mystery3, mystery4, mystery5];


// Add your functions below:
let validateCred = (arr) => {
    // create the array in reverse
    let cCard = Array.from(arr); // here we are creating a *shallow copy* of the array into the new variable
    cCard.reverse(); // and now we flip the copy around.
    if (cCard === arr) {  // both cCard and arr must reference the same object for this to be true!
      console.log("Debug: Objects have same reference"); // so we might see this on the console...
    }
    // array that will contain numbers to sum
    let cCard1 = [];
    // iterate through the array to: 
    // 1. double every other digit
    // 2. if the result is >9, do -9
    // 3. push each number to cCard1
    for (let i = 0; i < cCard.length; i++) {
        if (i % 2 === 0 /* even index */) {
            cCard1.push(cCard[i]);
        }
        else {
            // take number, *2
            if ((cCard[i] = cCard[i] * 2) > 9) {
                cCard[i] = cCard[i] - 9;
                cCard1.push(cCard[i]);
            } else {
                cCard1.push(cCard[i]);
            }
        }
    }

    // sum values in cCard1
    let sumCard1 = cCard1.reduce((a, b) => a + b);

    // Test module
    if (sumCard1 % 10 === 0) {
        return true
    } else {
        return false
    }
}

let invalidCards = [];
let validCards = [];

let findInvalidCards = (nArr) => {
    for (i = 0; i < nArr.length; i++) {
        if (validateCred(nArr[i]) === false) {
            invalidCards.push(nArr[i]);
        } else {
            validCards.push(nArr[i]);
        }
    }
}

findInvalidCards(batch);
console.log(invalidCards);
// console.log(validCards);

and so we get the following back, as expected, from the console:

[ [ 4, 5, 3, 2, 7, 7, 8, 7, 7, 1, 0, 9, 1, 7, 9, 5 ],
  [ 5, 7, 9, 5, 5, 9, 3, 3, 9, 2, 1, 3, 4, 6, 4, 3 ],
  [ 3, 7, 5, 7, 9, 6, 0, 8, 4, 4, 5, 9, 9, 1, 4 ],
  [ 6, 0, 1, 1, 1, 2, 7, 9, 6, 1, 7, 7, 7, 9, 3, 5 ],
  [ 5, 3, 8, 2, 0, 1, 9, 7, 7, 2, 8, 8, 3, 8, 5, 4 ],
  [ 3, 4, 4, 8, 0, 1, 9, 6, 8, 3, 0, 5, 4, 1, 4 ],
  [ 6, 0, 1, 1, 3, 7, 7, 0, 2, 0, 9, 6, 2, 6, 5, 6, 2, 0, 3 ],
  [ 4, 9, 2, 9, 8, 7, 7, 1, 6, 9, 2, 1, 7, 0, 9, 3 ] ]

Does that make sense? :slight_smile:

2 Likes

Oh, wow! Thank you so much for the generosity, the detailed explanation has been incredibly helpful. Have a great weekend!

1 Like

No problem. :slight_smile:

I wasn’t sure (as I’ve not completed that particular course here on Codecademy, yet) whether the JavaScript material went into any detail around how JavaScript behaves when you use the assignment operator to put one variable/object into another, so it seemed easier to explain why your code was working - in the sense that it produced an output with no error messages - but not producing what was expected. :slight_smile:

If you get stuck with anything else, pop back and see us. :slight_smile:

1 Like