0

I'm not really sure how to title this one, so if someone knows better, be my guest.

Basically, using nested for-loops, I'm trying to generate a 2-d array where each row starts at one number higher than the previous row, and then loops around on itself, so that the total of each row remains equal. Let me rather just show you what I mean:

[
  [1, 2, 3], // 1 + 2 + 3 = 6
  [2, 3, 1], // 2 + 3 + 1 = 6
  [3, 1, 2], // 3 + 1 + 2 = 6
]

See how every row is just 1, 2, 3 but every following row starts at i + 1 and when it reaches 3 it "resets" back to 1? That's what I'm trying to achieve.

Here's what I have so far:

const grid = []
const gridSize = 3

for(let i = 0; i < gridSize; i++) {
  const row = []

  for(let j = 0; j < gridSize; j++) {
    row.push(/* what goes here?? this is where I get stuck */)
  }

  grid.push(row)
}
SeriousLee
  • 1,301
  • 4
  • 20
  • 42

3 Answers3

2

You can add the row and column index together and mod by the size. If you want the values to start at 1 (offset), just add 1 to the result of each cell when mapping.

const generateMatrix = (size, offset = 1) =>
  Array.from({ length: size }, (_, rowIndex) =>
    Array.from({ length: size }, (__, colIndex) =>
      ((rowIndex + colIndex) % size) + offset));

const formatMatrix = (matrix) => matrix.map(row => row.join(' ')).join('\n');

console.log(formatMatrix(generateMatrix(2)));
console.log(formatMatrix(generateMatrix(3)));
console.log(formatMatrix(generateMatrix(4)));
.as-console-wrapper { top: 0; max-height: 100% !important; }

Here is a version with traditional for-loops:

const generateMatrix = (size, offset = 1) => {
  const matrix = [];
  for (let rowIndex = 0; rowIndex < size; rowIndex++) {
    const row = [];
    for (let colIndex = 0; colIndex < size; colIndex++) {
      row.push(((rowIndex + colIndex) % size) + offset);
    }
    matrix.push(row);
  }
  return matrix;
};

const formatMatrix = (matrix) => matrix.map(row => row.join(' ')).join('\n');

console.log(formatMatrix(generateMatrix(2)));
console.log(formatMatrix(generateMatrix(3)));
console.log(formatMatrix(generateMatrix(4)));
.as-console-wrapper { top: 0; max-height: 100% !important; }
Mr. Polywhirl
  • 42,981
  • 12
  • 84
  • 132
1

You can use Array(n).fill() to populate arrays. map the values generated with the inner function. It returns the sub-arrays that start at the current array index. Modulo % is used to wrap the sub-array when it reaches the end. +1 is used to shift the values so that they start at 1 instead of 0.

const n = 3;
const arr2D= Array(n)
  .fill()
  .map((_, i) => Array(n)
    .fill()
    .map((_, j) => ((i + j) % n) + 1)
  );

console.log(arr2D)
protob
  • 3,317
  • 1
  • 8
  • 19
1

Here's an approach that I find easy to read.

const gridSize = 3;
let grid = [];
let row = [];

//build the original row
for (let i = 1; i <= gridSize; i++) {
  row.push(i);
}
//push the original row onto the grid
grid.push(row);

//make a copy of the row by value https://stackoverflow.com/a/7486130/1024832
let newRow = row.slice();

for (let i = 1; i < gridSize; i++) {
  //copy the prior row (by value)
  newRow = newRow.slice();
  //shift the first element
  let firstElement = newRow.shift();
  //append the shifted element to the end of the row
  newRow.push(firstElement);
  //push the new row onto the grid
  grid.push(newRow);
}

console.log(grid);
Marc
  • 11,403
  • 2
  • 35
  • 45