Solving "Steamroller" / freeCodeCamp Algorithm Challenges

virenb

Viren B

Posted on July 31, 2020

Solving "Steamroller" / freeCodeCamp Algorithm Challenges

'Steamroller'

Let's solve freeCodeCamp's intermediate algorithm scripting challenge, 'Steamroller'.

Starter Code

function steamrollArray(arr) {
  return arr;
}

steamrollArray([1, [2], [3, [[4]]]]);

Instructions

Flatten a nested array. You must account for varying levels of nesting.

Test Cases (& Rules)

  • steamrollArray([[["a"]], [["b"]]]) should return ["a", "b"].
  • steamrollArray([1, [2], [3, [[4]]]]) should return [1, 2, 3, 4].
  • steamrollArray([1, [], [3, [[4]]]]) should return [1, 3, 4].
  • steamrollArray([1, {}, [3, [[4]]]]) should return [1, {}, 3, 4].
  • Your solution should not use the Array.prototype.flat() or Array.prototype.flatMap() methods.

Our Approach

After reading the instructions, starter code, and test cases more than once, this is what we're working with:

  • Our function takes in one argument, arr, which is an array of subarrays (contains numbers, strings, objects).
  • We must return the array flattened (see test cases).
  • Must do this without methods such as flat() or flatMap().

Looking at all the test cases, we have some interesting cases like [[4]]] as an index in arr. We need to go visit each index and remove them from an array, if they are in one.

The first thing I will do is create an empty array, to hold our new flattened array.

let flattened = [];

As we have to visit each index of arr, I figured to use the method, map().

MDN: Array.map()

arr.map((val) => {
  // more code coming
})

What are we going to do at each index though? There is another array method, isArray(), to check if the value is an array or not. It will return true or false.

MDN: Array.isArray()

If the value in the index is not an array, we can add it into our new flattened array.

arr.map((val) => {
  if (!Array.isArray(val)) {
    flattened.push(val);
  }
  else {
    // see below
  }
})

That is not too complex. For our else statement, how are we handling the indexes which contain an array?

We can use the ... operator in the else statement on steamrollArray() so it will be called and flatten the array each loop. This is a recursive fashion (I believe).

arr.map((val) => {
  if (!Array.isArray(val)) {
    flattened.push(val);
  }
  else {
    flattened.push(...steamrollArray(val));
  }
})

If our arr is [[[1]], 2], our first val is [[1]]. It will not pass the if statement since it is in an array so it will be evaluated by the else statement. We're calling the same flattened.push but not on the val. We're pushing ...steamrollArray(val), which will run the function again but it flattens val with each execution. Once it is out of the subarray, it will be pushed into flattened.

Make sure to return flattened.

Our Solution

function steamrollArray(arr) {
  let flattened = [];

  arr.map(val => {
    if (!Array.isArray(val)) {
      flattened.push(val);
    }
    else {
      flattened.push(...steamrollArray(val));
    }
  })

  return flattened;
}

Links & Resources

'Steamroller' Challenge on fCC

freeCodeCamp

Donate to FCC!

Solution on my GitHub

Thank you for reading!

💖 💪 🙅 🚩
virenb
Viren B

Posted on July 31, 2020

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related