freeCodeCamp Algorithm Challenge Guide: Chunky Monkey

freeCodeCamp Algorithm Challenge Guide: Chunky Monkey
0.0 0

#1

:triangular_flag_on_post: Remember to use Read-Search-Ask if you get stuck. Try to pair program :busts_in_silhouette: and write your own code :pencil:

:checkered_flag: Problem Explanation:

Our goal for this Algorithm is to split arr (first argument) into smaller chunks of arrays with the length provided by size (second argument). There are 4 green checks (objectives) our code needs to pass in order to complete this Algorithm:

  1. (['a', 'b', 'c', 'd'], 2) is expected to be [['a', 'b'], ['c', 'd']]
  2. ([0, 1, 2, 3, 4, 5], 3) is expected to be [[0, 1, 2], [3, 4, 5]]
  3. ([0, 1, 2, 3, 4, 5], 2) is expected to be [[0, 1], [2, 3], [4, 5]]
  4. ([0, 1, 2, 3, 4, 5], 4) is expected to be [[0, 1, 2, 3], [4, 5]]

Relevant Links

:speech_balloon: Hint: 1

The links above suggest to use Array.push(), so let’s start by first creating a new array to store the smaller arrays we will soon have like this:

var newArray = [];

try to solve the problem now

:speech_balloon: Hint: 2

Next we’ll need a for loop to loop through arr.

try to solve the problem now

:speech_balloon: Hint: 3

Finally, we need a method to do the actual splitting and we can use Array.slice() to do that. The key to this Algorithm is understanding how a for loop, size, Array.slice() and Array.push() all work together.

try to solve the problem now

Spoiler Alert!

687474703a2f2f7777772e796f75726472756d2e636f6d2f796f75726472756d2f696d616765732f323030372f31302f31302f7265645f7761726e696e675f7369676e5f322e676966.gif

Solution ahead!

:beginner: Basic Code Solution:

function chunkArrayInGroups(arr, size) {

  var temp = [];
  var result = [];

  for (var a = 0; a < arr.length; a++) {
    if (a % size !== size - 1)
      temp.push(arr[a]);
    else {
      temp.push(arr[a]);
      result.push(temp);
      temp = [];
    }
  }

  if (temp.length !== 0)
    result.push(temp);
  return result;
}

:rocket: Run Code

Code Explanation:

  • Firstly, we create two empty arrays called temp and result, which we will eventually return.
  • Our for loop loops until a is equal to or more than the length of the array in our test.
  • Inside our loop, we push to temp using temp.push(arr[a]); if the remainder of a / size is not equal to size - 1.
  • Otherwise, we push to temp, push temp to the result variable and reset temp to an empty array.
  • Next, if temp isn’t an empty array, we push it to result.
  • Finally, we return the value of result.

Relevant Links

:sunflower: Intermediate Code Solution:

function chunkArrayInGroups(arr, size) {
  // Break it up.
  var arr2 = [];
  for (var i = 0; i < arr.length; i+=size) {
	arr2.push(arr.slice(i , i+size));
  }
  return arr2;
}

:rocket: Run Code

Code Explanation:

  • First, we create an empty array arr2 where we will store our ‘chunks’.
  • The for loop starts at zero, increments by size each time through the loop, and stops when it reaches arr.length.
  • Note that this for loop does not loop through arr. Instead, we are using the loop to generate numbers we can use as indices to slice the array in the right locations.
  • Inside our loop, we create each chunk using arr.slice(i, i+size), and add this value to arr2 with arr2.push().
  • Finally, we return the value of arr2.

Relevant Links

:rotating_light: Advanced Code Solution:

function chunkArrayInGroups(arr, size) {
  // Break it up.
  var newArr = [];
  var i = 0;

  while (i < arr.length) {
    newArr.push(arr.slice(i, i+size));
    i += size;
  }
  return newArr;
}
chunkArrayInGroups(["a", "b", "c", "d"], 2);

:rocket: Run Code

Code Explanation:

  • Firstly, we create two variables. newArr is an empty array which we will push to. We also have the i variable set to zero, for use in our while loop.
  • Our while loop loops until i is equal to or more than the length of the array in our test.
  • Inside our loop, we push to the newArr array using arr.slice(i, i+size). For the first time it loops, it will look something like:
newArr.push(arr.slice(0, 0+2))
  • After we push to newArr, we add the variable of size onto i.
  • Finally, we return the value of newArr.

Relevant Links

:rotating_light: Advanced Code Solution 2:

function chunkArrayInGroups(arr, size) {
  var newArr = [];
  while (arr.length) {
    newArr.push(arr.splice(0,size));
  }
  return newArr;
}

:rocket: Run Code

Code Explanation:

  • Firstly, we create a variable. newArr is an empty array which we will push to.
  • Our while loop loops until the length of the array in our test is not 0.
  • Inside our loop, we push to the newArr array using arr.splice(0, size).
  • For each iteration of while loop, it deletes size number of elements from the front of arr and push them as an array to newArr.
  • Finally, we return the value of newArr.

Relevant Links

:clipboard: NOTES FOR CONTRIBUTIONS:

  • :warning: DO NOT add solutions that are similar to any existing solutions. If you think it is similar but better, then try to merge (or replace) the existing similar solution.
  • Add an explanation of your solution.
  • Categorize the solution in one of the following categories — Basic, Intermediate and Advanced. :traffic_light:
  • Please add your username only if you have added any relevant main contents. (:warning: DO NOT remove any existing usernames)

See :point_right: Wiki Challenge Solution Template for reference.


Confused on this explanation
Chunky Monkey_Tips on how to set number of group divisions
Chunk Monkey, 2d arrays
Did sub-sections on the Wiki just break?
Is this code solution correct?
#2

It’s important to see if any of those solutions doesn’t hang up when the size passed is 0 or less, which may cause an infinite loop.


#3

Why is the while loop the advanced solution? I had the intermediate one and to me it’s easier to read. Is it because while loops are faster? If so, is the difference significant?


#4

#5

#6

@Naqin I don’t understand it either, I came up with this:

function chunkArrayInGroups(arr, size) {
  var newArr = [];
  var index = 0;
  
  while (index < arr.length){
    newArr.push(arr.slice(index,index+size));
    index += size;
  }
  
  return newArr;
}

Which I suppose is the advanced one, but afterwards I thought that I could have optimized it further for readability, if I did, I would have ended with the for intermediate solution, but in the end I didn’t as it doesn’t seem to be much of a difference :grin:

So I’m also wondering which one is faster in this situation, for or while.


#7

I know in C#.Net For Loops are faster than While and For…In Loops.

Here is a the runs performance tests for array loops, Fastest array loops in Javascript.

The website indicates having the array.length in a variable like len is faster than a normal For Loop.

Below listed in order of fastest

For loop, i -= 1 II

var i;
for (i = arr.length; i > 0; i -= 1) {
  someFn(i);
}

For loop, cached

for (var i = 0, len = arr.length; i < len; i++) {
  someFn(i);
}

For loop, basic

for (var i = 0; i < arr.length; i++) {
  someFn(i);
}

#8

My first recursive algorithm. I’m beaming with joy.

function chunkArrayInGroups(arr, size) {
  // Break it up.
  var mArr = [];
 
  function newChunks (arr, size, mArr){
    if (arr.length > 0 ){
      mArr.push(arr.splice(0, size));
      newChunks(arr, size, mArr);
    }

  }
  newChunks(arr, size, mArr);
  return mArr;
}

chunkArrayInGroups([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14], 3);

#9

@Naqin I don’t think it has to do with the while loop. I think it may have something to do with the fact that the solution is using the .splice() method, which alters the original array. Unless you know exactly what you are doing it is kind of risky to alter the array while you are using it.

Just my thoughts


#10

I came up with

function chunkArrayInGroups(arr, size) {
  
 var result = [];
  
 for (var i=0; i<arr.length/size; i++){
   result.push(arr.slice(size*i, size*(i+1)));
 }
  return result;
}

is there any reason why this would be a bad code?


#11

This worked for me. Feedback, anyone?

function chunkArrayInGroups(arr, size) {
  newArr = [];
  var stop = size;
  for(var i = 0; i < arr.length; i += size) {
    newArr.push(arr.slice(i, stop));
    stop += size;
  }
  return newArr;
}

chunkArrayInGroups(["a", "b", "c", "d"], 2);

#12

wow nice solution! why did you call newChunks again down at the bottom?


#13

The first time you see function newChunks, I’m declaring the function. Inside the function newChunks I then call it inside itself so it automatically repeats (the recursion). Basically you are saying do function newChunks and then do it again indefinitely. This is why you need a condition in the function so it doesn’t go on forever.

Then finally at the bottom, I am actually calling the function for the first time so it runs.


#14

For cycle without cycle’s variable increment/decrement

function chunkArrayInGroups(arr, size) {
  var ar = [];
    for (i = 0; i < arr.length;) ar.push(arr.splice(i, size));
  return ar;
}

chunkArrayInGroups([0, 1, 2, 3, 4, 5, 6, 7, 8], 4);

#15

Hey lbarjak, I know the final-expression in a for statement is optional, but how does the loop know to continue incrementing or updating the counter variable?


#16

The variable is arr.length only. I use splice instead slice.


#17

How about this solution?

const chunkArrayInGroups = (arr, size) =>
  [...Array(Math.ceil(arr.length / size))].map((val, i) => 
    arr.slice(i * size, (i + 1) * size));

#18
// Using splice.
// Found splice very useful in this case.
    function chunkArrayInGroups(arr, size) {
      // Break it up.
        var arr1=[];
      while (arr.length>0) {
        arr1.push (arr.splice(0,size));
      }
      return arr1;
    }

    chunkArrayInGroups(["a", "b", "c", "d", "e"], 3);

#19
// Another solution, pretty exhaustive:
function chunkArrayInGroups(arr, size) {
  // Break it up.
    var arr1=[];
  var tempSize=0;
  var tempArr=[];
  while (arr.length>0) {
    tempArr.push(arr.shift());
    tempSize++;
    if (tempSize===size) {
      arr1.push(tempArr);
      tempSize=0;
      tempArr=[];
    } else if (arr.length===0) {
      arr1.push (tempArr);
    }
  }
  return arr1;
}

chunkArrayInGroups(["a", "b", "c", "d"], 2);

#20

i managed to solve this by :slight_smile:

function chunkArrayInGroups(arr, size) {
var result = [];
if (size <= 0){
return “increase the size please!!!”;
}

for ( i =0 ; arr.length > i ; arr.length-size){

result.push(arr.splice(0,size));}
return result;

}

chunkArrayInGroups([“a”, “b”, “c”, “d”], 0);