yenren
yenren

Reputation: 502

Fill diagonals of array with same values in JS

Given n and values array (values.length = 2 * n - 1), I want to fill an array of n x n elements, in a way that its diagonals will have the same values as follows:

ex. n = 3, values = [0, 1, 2, 3, 4]:

0 1 2
3 0 1
4 3 0

arr = [0, 1, 2, 3, 0, 1, 4, 3, 0]

ex. n = 4, values = [0, 1, 2, 3, 4, 5, 6];

0 1 2 3
4 0 1 2
5 4 0 1
6 5 4 0

arr = [0, 1, 2, 3, 4, 0, 1, 2, 5, 4, 0, 1, 6, 5, 4, 0]

I was able to fill upper half of the array using the following code, but got stuck with the rest:

var n = 3;
var values = [0, 1, 2, 3, 4]

var a = [];
for (var i = 0; i < n; i++) {
    for (var j = 0; j < n; j++) {
        a[j * n + i] = values[i - j];
    }
}

/* Result
0 1 2
  0 1
    0

arr = [0, 1, 2, undefined, 0, 1, undefined, undefined, 0]

Expected output:
0 1 2
3 0 1
4 3 0

arr = [0, 1, 2, 3, 0, 1, 4, 3, 0] */

Length of values array is 2 * n - 1, which is the count of diagonals of the array.

Any ideas how to fill the whole array?

Upvotes: 0

Views: 143

Answers (3)

jsN00b
jsN00b

Reputation: 3691

Presented below is one possible implementation that achieves the desired objective:

const values = [0, 1, 2, 3, 4];

const getCustomArray = (n = 3, val = values) => {
  const res = [...Array(n)].map(x => [...Array(n).fill(-1)]);
  for (let i = 0; i < n; i++) {
    res[i][i] = val[0];
    for (let j = 1; i + j < n; j++) {
      res[i][i+j] = val[j];
      res[i+j][i] = val[n + j - 1]
    }
  }
  return res.map(r => r.join(' ')).join('\n');
};

console.log('3 x 3 array:\n' + getCustomArray());

console.log('4 x 4 array:\n'+ getCustomArray(4, [...Array(2 * 4 -1).keys()]));

console.log('5 x 5 array:\n'+ getCustomArray(5, [...Array(2 * 5 -1).keys()]));

console.log('9 x 9 array:\n'+ getCustomArray(9, [...Array(2 * 9 -1).keys()]));

Approach

  • First, an array of n rows & n columns is created & filled with some value (such as -1).
  • Next, the i for-loop iterates over the set of diagonals
  • The 0,0, 1,1, 2,2 diagonal elements are set to the first element of the values array (typically 0).
  • Now, a second j for-loop iterates.
  • It updates the upper & lower diagonals.
  • res[i][i+j] targets the upper diagonals (such as 0,1, 1,2, 2,3, ...) and populates using values array
  • res[i+j][j] targets the lower diagonals (such as 1,0, 2,1, 3,2, ...) and populates by using an offset of n - 1 to index the values array

Please add any questions or feedback on the comments.

Upvotes: 2

The Bomb Squad
The Bomb Squad

Reputation: 4337

Ok, I saw the requested results and made this snippet below I use a two dimensional array to be able to check if there is an existing diagonal using x y logic and if there was not, there was a counter that would reference the next array number(c+1%arr.length)

EDIT EXPLAINED: I saw what was going on then I decided to try only adding when there was no diagonal in that "place".. it works like a charm 👌

var arr=[0,1,2,3,4]

function makeBox(arr,n){
  var toReturn=[], c=0
  for(let i=0;i<n*n;i++){
    let y=(i-(i%n))/n, x=i%n
    let diagonal=toReturn[y-1]?toReturn[y-1][x-1]:undefined
    let isDiagonal=typeof diagonal==="number" //0 is a number
    toReturn[y]?toReturn[y].push(isDiagonal?diagonal:arr[c]):
    toReturn[y]=[isDiagonal?diagonal:arr[c]]
    if(!isDiagonal){c=(c+1)%arr.length}
  }
  return toReturn.map(a=>a.join(' ')).join('\n')
}

console.log(makeBox(arr,3))
console.log(makeBox(arr,4))
console.log(makeBox(arr,6))
console.log("before you say that it doesn't work.. you just need the correctly sized array\nLook Below")
console.log(makeBox([0,1,2,3,4,5,6],4))

Upvotes: 2

AdamTheFirst
AdamTheFirst

Reputation: 151

Created while loop and added counter. Counter counts the elements suppose to be cut from end. first loop goes thru these elements and adds them to the beginning, second loop limited by this counter so it doesnt hit the end of the array and it adds the elemets havent been cutted from the array to the end. until all elements are cut from the array.

var values = [0, 1, 2, 3, 4]

var a = [];
var ctr = 0
while(ctr < values.length){
  for(let i = (values.length - ctr); i < values.length; i++){
    a.push(values[i]);
  }
  
  for(let i = 0; i < (values.length - ctr); i++){
    a.push(values[i]);
  }
  ctr++;
}

Output

[0, 1, 2, 3, 4, 4, 0, 1, 2, 3, 3, 4, 0, 1, 2, 2, 3, 4, 0, 1, 1, 2, 3, 4, 0]

0 1 2 3 4
4 0 1 2 3
3 4 0 1 2
2 3 4 0 1
1 2 3 4 0

Upvotes: 2

Related Questions