Matrix Addition (JavaScript)

Matrix Addition challenge instructions

Write a function that accepts two square matrices (nxn two dimensional arrays), and return the sum of the two. Both matrices being passed into the function will be of size nxn (square), containing only integers.

How to sum two matrices:
Take each cell [n][m] from the first matrix, and add it with the [n][m] cell from the second matrix. This will be cell [n][m] in the solution matrix.

Matrix Addition challenge instructions

Write a function that accepts two square matrices (nxn two dimensional arrays), and return the sum of the two. Both matrices being passed into the function will be of size nxn (square), containing only integers.

How to sum two matrices:
Take each cell [n][m] from the first matrix, and add it with the [n][m] cell from the second matrix. This will be cell [n][m] in the solution matrix.

Example function call:
matrixAddition( [ [1, 2, 3], [3, 2, 1,], [1, 1, 1] ], [ [2, 2, 1], [3, 2, 3], [1, 1, 3] ] );
returns [ [3, 4, 4], [6, 4, 4], [2, 2, 4] ]

1
2
3
4
Visualization:
|1 2 3|   |2 2 1|  |3 4 4|
|3 2 1| + |3 2 3| = |6 4 4|
|1 1 1|   |1 1 3|  |2 2 4|

Solution

To start off two things stand out right away in the instructions. The functions arguments will be two dimensional arrays of equal height and width (n) and the second thing is that both arrays will contain only integers. Because of this is isn’t necessary to do “number” checks during addition or test if the array indexes are “undefined” if we know they are defined in one arguments array then we also know that the same index will be defined in the second arguments array.

Here is the signature for the function that needs to be created, 2dArray function matrixAddition(2dArray a, 2dArray b). I’m going to make an empty array res which will be the result of function matrixAddition. Since both arguments are known to be arrays I can iterate through the array in argument a and access array members from argument b using the index number argument provided by the Array.forEach method.

1
2
3
4
5
6
7
8
function matrixAddition(a, b) {
"use strict";
var res = [];
a.forEach((t, n, a) => {
// TODO: Build arrays with added up indexes.
});
return res;
}

Alright, so now I have a loop through the first depth of the 2dArray a which values are also arrays. To do matrix addition simply add up the values inside the inner arrays with the corresponding values found on the inner 2dArray b. Inside a.forEach iteration I think using something like Array.reduce would work well to build up a new array containing the sums of each index from arrays a and b. I’m going to first try using a second Array.forEach because it’ll make the function easier to read and debug since both inner and outer functions will be iterated in identical fashion. If this works I can refactor the function to use Array.reduce, and if it doesn’t then I’ll have to plan a new way to attack this problem.

1
2
3
4
5
6
7
8
9
10
11
12
function matrixAddition(a, b) {
"use strict";
var res = [];
a.forEach((t, n1) => {
let sums = [];
t.forEach((num, n2) => {
sums.push(num + b[n1][n2]);
});
res.push(sums);
});
return res;
}

The first argument t in a.forEach is the value of the current index in the outer 2dArray a, the argument n1 is an index of 2dArray a where the value t is found. We can use n1 to reference the corresponding inner array on 2dArray b from the inner iteration t.forEach and use the t.forEach index argument which I labeled n2 to reference the numbers in 2dArray b by reading b[n1][n2]. The creator of the challenge provided a test and I wrote a custom test using the test suites <code>Test.assertSimilar method which compares that 2 values are equivalent. The first argument passed to assertSimilar is a call to matrixAddition and the second is the expected result:

1
2
3
4
5
6
Test.assertSimilar(
matrixAddition([[1, 2], [1, 2]], [[2, 3], [2, 3]])
, [[3, 5], [3, 5]]);
Test.assertSimilar(
matrixAddition([[1, 2, 3], [3, 2, 1], [1, 1, 1]], [[2, 2, 1], [3, 2, 3], [1, 1, 3]])
, [[3, 4, 4], [6, 4, 4], [2, 2, 4]]);

Both tests passed and now I know the algorithm works so I want to refactor it a bit for my final submission. I’ll change the inner Array.forEach to use Array.reduce instead which is what I planned from the start. The reduce iteration make more sense then using a second forEach because reduce builds a running calculations through an array and that is basically what we’re doing here. With Array.reduce we just need to keep in mind the signature change which becomes (callback, initialValue) where callback is our function to run against each value of array t) and the callback has parameters (previousValue, currentValue, currentIndex, array). I still like forEach on the outer iteration of 2dArray a because we want to run the reduce “for each” value inside the 2dArray a and a.forEach does that well. So here is my final submission.

My Final Solution

1
2
3
4
5
6
7
8
9
function matrixAddition(a, b) {
"use strict";
var res = [];
a.forEach((t, n) => {
res.push(t.reduce((sums, val, i) => sums.concat(val + b[n][i]), []));
});
return res;
}

Here is another submission made by users ColbyDauph, monkey123 and pachareal which utilizes Array.map and in the future I would use map over reduce as well because Array.map creates a new Array from the results of a function ran against the values of another Array which is perfect for this code challenge. I will agree that this is the best practice.

Best Practice

1
2
3
4
5
6
7
function matrixAddition(a, b){
return a.map(function(n, i){
return n.map(function(o, j){
return o + b[i][j];
});
});
}