Search code examples
javascriptarrayshigher-order-functions

N*N sized Identity Matrix using Higher Order Functions


I am trying to create an n * n identity matrix using only the methods in the Array.prototype (you are welcome to call other methods). I can create an n*n matrix using fill() but have trouble converting the diagonal elements into 1 without using if-else.

function matrix(n) {
  var nSizeArray = Array(n).fill().map(function(elem) {
    return Array(elem).fill(0).indexOf([elem][elem]=1)
  })
  return nSizeArray
}
matrix(5)

The above is just some demonstration of what I wished to do. I can't wrap my head around how to keep filling the array and accessing the [i][i] element in an array using the available array methods.


Solution

  • Edit: Oh well, I just saw that you wrote only the methods in the Array.prototype not just only functions... So I'm guessing you don't want to include Math functions either?

    The second parameter to the map is the index of the element, which we will use to fill the correct spots in the matrix with 1s.

    Now we need a way to assign a 1 at every position with i == j and a 0 at every other position without using the obvious if..else approach. We can use the fact that i == j is equivalent to i - j == 0.

    So now the task is to map every (i,j) with i - j == 0 to 1 and i - j != 0 to 0.

    We do this using this line:

    return 1 - Math.min(Math.abs(i-j),1);
    

    The Math.min(...) ensures that i - j == 0 is mapped to 0 and all other index combinations are mapped to 1 (since they result in |i-j| >= 1). By subtracting this result from 1 we can simply flip the bit and get our desired result:

    function matrix(n) {
      return Array(n).fill(0).map(function(elem, i) {
        return Array(n).fill(0).map(function(elem2, j) {
          return 1 - Math.min(Math.abs(i-j),1);
        });
      });
    }