Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to get the element which are diagonal to a certain index in an array which represents a rectangle

Consider an array whose length will be always product of two numbers. For below array l is 4 and w is 5.

There is also a given index. I want to get the two arrays containing elements which lie on the diagonal line which passes through that particular index.

[
    0,  1,  2,  3,  4
    5,  6,  7,  8,  9
    10, 11, 12, 13, 14
    15, 16, 17, 18, 19
]  

index = 7 => [3, 7, 11, 15] and [1, 7, 13, 19]
index = 16 => [4, 8, 12, 16] and [10, 16]
index = 0 => [0, 6, 12, 18] and [0]

I have tried following:

let arr = Array(20).fill().map((x,i) => i);

function getDias(arr, l, w, ind){
  let arr1 = [];
  let arr2 = [];
  
  for(let i = 0;i<l;i++){
    arr1.push(arr[ind + (i * w) + i])
    arr1.push(arr[ind - (i * w) - i])
    arr2.push(arr[ind + (i * w) + i])
    arr2.push(arr[ind - (i * w) - i])
  }
  const remove = arr => [...new Set(arr.filter(x => x !== undefined))];
  return [remove(arr1),remove(arr2)];

}
console.log(getDias(arr, 4, 5, 7))

The code have two problems. Both the arrays in the result are same. And secondly they are not in order.

Note: I don't want to use sort() to reorder the array. And also I don't want loop through all 20 elements. Just want to get the elements of that diagonal row

like image 756
Maheer Ali Avatar asked Jun 29 '19 04:06

Maheer Ali


2 Answers

Some math (ie, modulus, integer division, and minimums) can find the beginning row and column for both the diagonal that runs left-to-right (LTR) and right-to-left (RTL), saving complexity of iterating backwards to find the starting points. Then, using those beginning rows and columns, simply iterate until outside the height and width bounds of the array.

let arr = Array(20).fill().map((x, i) => i);

function diagonals(arr, h, w, n) {
  var nRow = Math.floor(n / w);
  var nCol = n % w;

  let LTR = [];
  for (let r = nRow - Math.min(nRow, nCol), c = nCol - Math.min(nRow, nCol); r < h && c < w; r++, c++) LTR.push(arr[r * w + c]);

  let RTL = [];
  for (let r = nRow - Math.min(nRow, w - nCol - 1), c = nCol + Math.min(nRow, w - nCol - 1); r < h && 0 <= c; r++, c--) RTL.push(arr[r * w + c]);

  return [LTR, RTL];
}

Sample runs...

diagonals(arr, 4, 5, 7);  // returns ==> [[1, 7, 13, 19], [3, 7, 11, 15]]
diagonals(arr, 4, 5, 15); // returns ==> [[15], [3, 7, 11, 15]]

Edit: Note on arr value vs index.

Also, just a point of clarification. The question indicates "There is also a given index. I want to get the two arrays containing elements which lie on the diagonal line which passes through that particular index." If the index of the rectangular array is being sought rather than the actual value of arr, then there is no need to build arr, and subsequently the function and push statements can be changed to...

  • function diagonals(h, w, n)
  • LTR.push(r * w + c)
  • RTL.push(r * w + c)
like image 179
Trentium Avatar answered Sep 30 '22 00:09

Trentium


Try the following code

let arr = Array(20).fill().map((x,i) => i);

function getDias(arr, l, w, ind){
  let arr1 = [];
  let arr2 = [];
  n = l*w;
  lVal = Math.floor(ind/w);
  rVal = ind%w;
  temp1  = lVal;
  temp2  = rVal;
  while(temp1>=0 && temp2>=0){
    val = ((w*temp1) + temp2);
    arr1.unshift(arr[val]);  
    temp1--;
    temp2--;
  }
  temp1  = lVal;
  temp2  = rVal;
  temp1++;
  temp2++;
  while(temp1<l && temp2<w){
    val = ((w*temp1) + temp2);
    arr1.push(arr[val]);  
    temp1++;
    temp2++;
  }

   
  console.log(arr1);
  temp1  = lVal;
  temp2  = rVal;
  while(temp1>=0 && temp2<w){
    val = ((w*temp1) + temp2);
    arr2.unshift(arr[val]);  
    temp1--;
    temp2++;
  }
  
  temp1  = lVal;
  temp2  = rVal;
  temp1++;
  temp2--;
  while(temp1<l && temp2>=0){
    val = ((w*temp1) + temp2);
    arr2.push(arr[val]);  
    temp1++;
    temp2--;
  }

  console.log(arr2);

}
getDias(arr, 4, 5, 7);
getDias(arr, 4, 5, 16);
getDias(arr, 4, 5, 0);

The idea is to compute l_val and r_val.

l_val = index/w
r_val = index%w

Now arr[l_val][r_val] marks the position in the matrix found by l_val* w+ r_val

This is now followed by 4 steps:

1) Start iteration from arr[l_val][r_val]. Subtract 1 from both till we reach the end. Unshift this to array_1 (to maintain order)

2) Start iteration from [l_val][r_val].Add 1 to both till we reach the end. Push this to array_1.

3) Start iteration from arr[l_val][r_val]. Subtract 1 from l_val and add 1 t r_val till we reach the end. Unshift this to array_2 (to maintain order)

4) Start iteration from [l_val][r_val].Add 1 to l_val and subtract 1 from r_val till we reach the end. Push this to array_2.

like image 24
Phenomenal One Avatar answered Sep 30 '22 00:09

Phenomenal One