freeCodeCamp Challenge Guide: Map the Debris

Map the Debris


Problem Explanation

The first thing to do is to get familiar with what the program is for by knowing what Orbital period exactly is. You’ve to return a new array that transforms the element’s average altitude into their orbital periods. The parts generally found hard are finding the formula, implementing it and for some people, modifying objects by the key. However, something that is not very clear is the fact that your program has to be able to check for any number of objects in the array; This is what is tested on the second part.

Relevant Links


Hints

Hint 1

The formula needed is:

Hint 2

Use Math.round() to round up to the next whole number as requested. Using Math.ceil() will let you pass the first test but fail the second one.

Hint 3

Find out how to remove and add key to a JavaScript object.


Solutions

Solution 1 (Click to Show/Hide)
function orbitalPeriod(arr) {
  var GM = 398600.4418;
  var earthRadius = 6367.4447;
  var a = 2 * Math.PI;
  var newArr = [];

  var getOrbPeriod = function(obj) {
    var c = Math.pow(earthRadius + obj.avgAlt, 3);
    var b = Math.sqrt(c / GM);
    var orbPeriod = Math.round(a * b);
    // create new object
    return {name: obj.name, orbitalPeriod: orbPeriod};
  };

  for (var elem in arr) {
    newArr.push(getOrbPeriod(arr[elem]));
  }

  return newArr;
}

// test here
orbitalPeriod([{ name: "sputnik", avgAlt: 35873.5553 }]);

Code Explanation

  • GM and earthRadius are both given to us.
  • To make the code easier to edit and read, each part of the equation is written separately.
  • Create newArr to store the orbPeriod's.
  • a is 2 times pi. The part that is a constant is on the global scope while the rest is part of a function.
  • Create a function, gerOrbPeriod() that will do the required work for any amount of objects.
  • c is (earthRadius + avgAlt) to the cube.
  • b is the square root of c divided by GM.
  • Create orbPeriod to store the product of a and b, with the Math.round() function applied to round up to the next whole number.
  • Then we delete the key avgAlt, and add the new key and its value.

Relevant Links

Solution 2 (Click to Show/Hide)
function orbitalPeriod(arr) {
  var GM = 398600.4418;
  var earthRadius = 6367.4447;
  var newArr = [];

  //Looping through each key in arr object
  for (var elem in arr) {
    //Rounding off the orbital period value
    var orbitalPer = Math.round(
      2 * Math.PI * Math.sqrt(Math.pow(arr[elem].avgAlt + earthRadius, 3) / GM)
    );
    //Adding new object with orbitalPeriod property
    newArr.push({name: arr[elem].name, orbitalPeriod: orbitalPer});
  }

  return newArr;
}

// test here
orbitalPeriod([{ name: "sputnik", avgAlt: 35873.5553 }]);

Code Explanation

  • GM and earthRadius are both given to us.
  • A for..in loop is used to iterate through each value in given array arr.
  • orbitalPer holds the value of orbital period for each iteration calculated using the formula.
  • The key avgAlt is deleted, and orbitalPer found is assigned in arr.
Solution 3 (Click to Show/Hide)
function orbitalPeriod(arr) {
  var GM = 398600.4418;
  var earthRadius = 6367.4447;
  // Create new array to prevent modification of the original
  var newArr = JSON.parse(JSON.stringify(arr));
  // Loop through each item in the array arr
  newArr.forEach(function(item) {
    // Calculate the Orbital period value
    var tmp = Math.round(
      2 * Math.PI * Math.sqrt(Math.pow(earthRadius + item.avgAlt, 3) / GM)
    );
    //Delete the avgAlt property
    delete item.avgAlt;
    //Add orbitalPeriod property
    item.orbitalPeriod = tmp;
  });
  return newArr;
}

// test here
orbitalPeriod([{ name: "sputnik", avgAlt: 35873.5553 }]);

Code Explanation

  • GM and earthRadius are both given to us.
  • The forEach() method is used to execute the function once per element (item) in arr.
  • tmp holds the value of orbital period for each element calculated using the formula.
  • The key avgAlt is deleted, and orbital period (tmp) found is assigned to the key orbitalPeriod.

Relevant Links

Solution 4 (Click to Show/Hide)
function orbitalPeriod(arr) {
  const GM = 398600.4418;
  const earthRadius = 6367.4447;
  return arr.map(({ name, avgAlt }) => {
    const earth = earthRadius + avgAlt;
    const orbitalPeriod = Math.round(2 * Math.PI * Math.sqrt(Math.pow(earth, 3)/GM));
    return { name, orbitalPeriod };
  });
}

orbitalPeriod([{name : "sputnik", avgAlt : 35873.5553}]);

16 Likes

You could get rid of the temporary variable by just adding the orbitalPeriod before deleting avgAlt.

function orbitalPeriod(arr) {
  var GM = 398600.4418;
  var earthRadius = 6367.4447;

  // Loop through each item in the array arr
  arr.forEach(function(item) {
    // Calculate the Orbital period
    //Add orbitalPeriod property
    item.orbitalPeriod = Math.round(2 * Math.PI * Math.sqrt(Math.pow(earthRadius + item.avgAlt, 3) / GM));;
    //Delete the avgAlt property
    delete item.avgAlt;
  });
  return arr;
}

// test here
orbitalPeriod([{name : "sputnik", avgAlt : 35873.5553}]);
4 Likes

…Another solution …

function orbitalPeriod(arr) {
  var GM = 398600.4418;
  var earthRadius = 6367.4447;
  return arr.map(function(el){
    return {name:el.name,
            orbitalPeriod:Math.round((2*Math.PI)*Math.sqrt(Math.pow(earthRadius+el.avgAlt,3)/GM))
    }
  });
}
10 Likes

This is exactly what i used, i don’t know why the advanced solution needs to be so complicated! Plus there is the added bonus of no mutation!

1 Like

I used this one too.
Now I’m wondering if maybe it’s better to mutate the given object(performance gain?) instead of creating new objects every time?

Honestly, mutating the input state is a big red flag for me! this opens up a world of bugs where you loose track of how an value (in this case, whatever the inserted ‘arr’ array was) was changed and by who.

And separately, i think the ‘performance gain’ you mention may be classified as ‘premature optimization’ as without knowledge of how often its used, how different the performance actually is from creating a new object and how critical the speed is you can quickly go from code thats easy to understand to go that works ‘better’ but is buggy because its harder to understand. Just remember that we (programmers) spend the majority of our time reading other peoples code so this is a key thing to keep in mind.

If you never mutate your input, and simply just return the result, without doing anything else outside this function, you can have the guarantee for the same input, it always has the same output. If you mutate the arr, this will likely break.

I made a code pen going from the advanced solution, which i don’t think is good (mutation) and then multiple examples of it being pure, each one introducing concepts like:

If your interesting in understanding more about it let me know :slight_smile:

4 Likes

Here is the code I used,

function orbitalPeriod(arr) {
  var GM = 398600.4418
  var earthRadius = 6367.4447
  
  for (let i in arr) {
    var orbitsLengthPower3 = Math.pow((arr[i].avgAlt + earthRadius), 3)
    var rightHand = Math.pow((orbitsLengthPower3 / GM), 0.5)
    var orbitalPer = Math.round(2 * Math.PI * rightHand)
    arr[i] = {name: arr[i].name, orbitalPeriod: orbitalPer}
  }
  return arr;
}

orbitalPeriod([{name: "iss", avgAlt: 413.6}, {name: "hubble", avgAlt: 556.7}, {name: "moon", avgAlt: 378632.553}])

short and sweet

With ES6:

function orbitalPeriod(arr) {
  var GM = 398600.4418;
  var earthRadius = 6367.4447;
  for(let i in arr){
    arr[i].orbitalPeriod = Math.round((2*Math.PI)*Math.sqrt(Math.pow((earthRadius+arr[i].avgAlt),3)/GM));
    delete arr[i].avgAlt;
  }
  return arr;
}

Without ES6:

function orbitalPeriod(arr) {
  var GM = 398600.4418;
  var earthRadius = 6367.4447;
  for(var i = 0; i < arr.length; i++){
    arr[i].orbitalPeriod = Math.round((2*Math.PI)*Math.sqrt(Math.pow((earthRadius+arr[i].avgAlt),3)/GM));
    delete arr[i].avgAlt;
  }
  return arr;
}
1 Like
function orbitalPeriod(arr) {
  var GM = 398600.4418;
  var earthRadius = 6367.4447;

  var resultArr = arr.reduce(function(accu, value, index, array){
    var result =   Math.round(2 * Math.PI * Math.sqrt(Math.pow(earthRadius + value.avgAlt, 3)/GM));
    return accu.concat({name: value.name, orbitalPeriod: result}); 
  }, []);

  return resultArr;
}
2 Likes

Advanced solution above ^^^ is terrible! This was a breeze after last challenge I thought!

function orbitalPeriod(a) {
  return a.map(p => {
    return {
      name: p.name,
      orbitalPeriod: Math.round(2 * Math.PI * Math.sqrt(Math.pow((p.avgAlt + 6367.4447), 3) / 398600.4418 ))
    }
  })
}
4 Likes