Reputation: 502
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
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
n
rows & n
columns is created & filled with some value (such as -1
).i
for-loop iterates over the set of diagonals0,0
, 1,1
, 2,2
diagonal elements are set to the first element of the values
array (typically 0
).j
for-loop iterates.res[i][i+j]
targets the upper diagonals (such as 0,1
, 1,2
, 2,3
, ...) and populates using values
arrayres[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
arrayPlease add any questions or feedback on the comments.
Upvotes: 2
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
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