Проблема при преобразовании массива 6 * 6 в массив 3 * 3 в javascript

#javascript #arrays

#javascript #массивы

Вопрос:

Я пытаюсь решить вопрос о ранге хакера, и вот ссылка на вопрос.

В вопросе я преобразую массив (6 * 6) в массив 3 * 3 и передаю другой функции. При преобразовании массива 3 * 3 структура arrray, требуемая в соответствии с требованиями вопроса, не получается

Я отлаживал с помощью консоли.оператор журнала и поиск в Google для дальнейших шагов. Я застрял со структурированием массива в соответствии с требованиями вопроса

Тем не менее, один тестовый пример прошел при запуске кода в ранге хакера. можете ли вы помочь мне разобраться с ошибками?

фрагмент кода:

 function getSubArray(arr, tlc, size) {
  var a = new Array();
  for (var i = tlc[0]; i < size   tlc[0]; i  ) {
    var b = new Array();
    for (var j = tlc[0]; j < size   tlc[0]; j  ) {
      //if ((i==tlc[0]) || (i == tlc[0] size)-1)
      b.push(arr[i][j]);
      //}
      if (i == tlc[0]   1) {
        //b[i][tlc[1]] = 0;
        b[i].pop();
        b[i].shift();
        //b[i][tlc[size   tlc[1]]] = 0;
      }
      //console.log(b);
    }
    a.push(b);
  }
  console.log(a);
  return a;
};
  

Полный код:

 /*
  Let's simply represent this entire problem space differently. 
  Let's reconceive homogeneous, higher-order, JS arrays as two-
  dimensional, algebraic arrays instead of JS arrays, since JS 
  is not natively well-suited for this. 

  First, a few utility functions for handling arrays...
*/

// calculate and return the sums of all the desired subarrays - 
// relies on functions that treat JS arrays *differently*;
// current implementations assumes that square subarrays of shape 
// {size x size} are desired
function calcSubSums(arr, size) {
  var sums = new Array();
  console.log(arr.length);
  for (var i = 0; i < arr.length - size   1; i  ) {
    for (var j = 0; j < arr[i].length - size   1; j  ) {
      sums.push(reduce(ravel(getSubArray(arr, [i, j], size))));
    }
  }
  return sums;
};

// for an array, arr, return subarray that starts at the top-left-
// corner indexes tlc (top-row-index, left-column-index) for an 
// extent of size on each dimension
function getSubArray(arr, tlc, size) {
  var a = new Array();
  for (var i = tlc[0]; i < size   tlc[0]; i  ) {
    var b = new Array();
    for (var j = tlc[0]; j < size   tlc[0]; j  ) {
      //if ((i==tlc[0]) || (i == tlc[0] size)-1)
      b.push(arr[i][j]);
      //}
      if (i == tlc[0]   1) {
        //b[i][tlc[1]] = 0;
        b[i].pop();
        b[i].shift();
        //b[i][tlc[size   tlc[1]]] = 0;
      }
      //console.log(b);
    }
    a.push(b);
  }
  console.log(a);
  return a;
};

// convert a higher dimensional array into one-dimensional array 
// that contains all of its elements, unpacking from top-to-bottom, 
// left-to-right
function ravel(arr, flat) {
  // If flat - accumulator array - not yet defined, create it.
  if ('undefined' == typeof flat) flat = new Array();
  // If arg is an array, iterate over the elements in index order.
  if (isArray(arr)) {
    // Call self recursively to get elements or process next, 
    // outermost level of nesting.
    for (var i = 0; i < arr.length; i  ) {
      ravel(arr[i], flat);
    }
  }
  // Otherwise, just add simple element to accumulator.
  else flat.push(arr);
  // Return accumulated values.
  return flat;
};

// return a Boolean indicator of whether the argument is a JS array
function isArray(a) {
  if ('undefined' == typeof a) {
    return false
  };
  return -1 != a.constructor.toString().indexOf('Array');
};

// place the operator {op} between the elements of a and evaluate the 
// entire, resulting expression
function reduce(a, op) {
  // Set default op (add/concatenate), if not given.
  //console.log(a);
  if ('undefined' == typeof op) op = ' ';
  // Initialize command to evaluate.
  var cmd = '';
  // Compose command string - concatenate each element with op.
  for (var i = 0; i < a.length; i  ) {
    cmd  = a[i]   op;
  }
  // Remove, extraneous, trailing instance of op and return evaluation.
  //console.log(cmd.length);
  //console.log(op.length);
  return eval(cmd.substring(0, cmd.length - op.length));
};

// now let's test it...
window.onload = function() {
  // declare the test array
  var array = [
    [0, 0, 0, 0, 0, 0],
    [5, 5, 5, 0, 0, 0],
    [10, 10, 10, 0, 0, 0],
    [0, 0, 0, 0, 0, 0],
    [5, 5, 5, 0, 0, 0],
    [10, 10, 10, 0, 0, 0]
  ];
  // calculate all of the sums of 3x3 subset arrays of our test array 
  // and write the totals to the console
  console.log(calcSubSums(array, 3));
};  

Комментарии:

1. Пожалуйста, разместите здесь описание проблемы, а не просто ссылку. Наши вопросы не должны зависеть от других сайтов.

2. Фрагмент выдает ошибку

3. Я предлагаю вам напрямую суммировать требуемые места, используя вложенные for , нет необходимости в подмассиве и все. Проверьте ограничения, которые очень понятны

4. «структура arrray, требуемая требованиями к вопросу» : задача, на которую вы ссылаетесь, не требует структуры массива в качестве выходных данных.

Ответ №1:

К сожалению, Javascript — это не python, поэтому для решения этой проблемы вам сначала придется расширить стандартную библиотеку. Но как только с этим покончено, остальная часть программы проста:

 // "library"

function* iter(it) {
    yield* it;
}

function* zip(...its) {
    its = its.map(iter);
    while (true) {
        let rs = its.map(it => it.next());
        if (rs.some(r => r.done))
            break;
        yield rs.map(r => r.value);
    }
}

function* slice(it, n) {
    for (let x of it) {
        if (--n < 0)
            yield x;
    }
}

function sum(it) {
    let s = 0;
    for (let x of it)
        s  = x;
    return s;
}

function max(it) {
    let s = -Infinity;
    for (let x of it)
        s = x > s ? x : s;
    return s;
}

// "your program"

function* triples(a) {
    yield* zip(a, slice(a, 1), slice(a, 2));
}

function* sums(mat) {
    for (let rows of triples(mat))
        for (let [s0, s1, s2] of zip(...rows.map(triples)))
            yield sum(s0)   s1[1]   sum(s2);
}

function solution(mat) {
    return max(sums(mat));
}

// "test"

let test = [
    [-9, -9, -9, 1, 1, 1,],
    [0, -9, 0, 4, 3, 2,],
    [-9, -9, -9, 1, 2, 3,],
    [0, 0, 8, 6, 6, 0,],
    [0, 0, 0, -2, 0, 0,],
    [0, 0, 1, 2, 4, 0,],
];

console.log(solution(test));  

Ключевой функцией является triples , которая превращается 1 2 3 4 5 6 в 123 234 345 456 . Мы применяем его к самой матрице, предоставляя нам скользящие группы из трех строк, а затем снова к каждой строке в группе, давая нам подматрицы 3×3. Все, что осталось, это суммировать их и найти максимальное значение.

Конечно, это также можно решить тривиально с помощью индексов:

 let m = [
    [-9, -9, -9, 1, 1, 1,],
    [0, -9, 0, 4, 3, 2,],
    [-9, -9, -9, 1, 2, 3,],
    [0, 0, 8, 6, 6, 0,],
    [0, 0, 0, -2, 0, 0,],
    [0, 0, 1, 2, 4, 0,],
];


let len = m.length;

let sums = [];

for (let r = 0; r < len - 2; r  )
    for (let c = 0; c < len - 2; c  )
        sums.push(
            m[r][c]   m[r][c   1]   m[r][c   2]  
            m[r   1][c   1]  
            m[r   2][c]   m[r   2][c   1]   m[r   2][c   2]
        );


console.log(Math.max(...sums))  

но, эй, в чем прикол?

Комментарии:

1. 2 тестовый пример не удался, попробуйте использовать указанную ссылку

2. здесь

3. @AswinKumar: да, какая именно матрица не работает?

4. Этот [[-1,-1,0,-9,-2,-2],[-2,-1,-6,-8,-2,-5],[-1,-1,-1,-2,-3,-4],[-1,-9,-2,-4,-4,-5],[-7,-3,-3,-2,-9,-9],[-1,-3,-1,-2,-4,-5]]

5. @georg … большое спасибо за ваш ответ… код сработал… ваши предложения действительно полезны для меня

Ответ №2:

Проблема заключается в вычислении максимальной суммы значений в позиции песочных часов, поэтому нет смысла разбивать на несколько подмассивов.

 function calcSubSums(arr) {
  let max = -Infinity
  for (let x = 0; x <= arr.length - 3; x  ) {
    for (let y = 0; y <= arr.length - 3; y  ) {
      // sum the top row
      let sum = arr[x][y]   arr[x][y   1]   arr[x][y   2]

      // sum the middle row
      sum  = arr[x   1][y   1]

      // sum the bottom row
      sum  = arr[x   2][y]   arr[x   2][y   1]   arr[x   2][y   2]

      max = Math.max(max, sum)
    }
  }
  return max
}


var array = [
  [0, 0, 0, 0, 0, 0],
  [5, 5, 5, 0, 0, 0],
  [10, 10, 10, 0, 0, 0],
  [0, 0, 0, 0, 0, 0],
  [5, 5, 5, 0, 0, 0],
  [10, 10, 10, 0, 0, 0]
];

console.log(calcSubSums(array));  

Комментарии:

1. большое спасибо за ваш ответ… код сработал… ваши предложения действительно полезны для меня

Ответ №3:

В вашем вопросе неясно, пытаетесь ли вы решить это определенным образом в качестве упражнения или просто решить его. Похоже, у вас много кода для того, что составляет два цикла. Я прошу прощения, если я упускаю суть, но подумал, что я бы опубликовал это как простое решение, которое в основном проходит через массив строка за строкой и столбец за столбцом:

 let test = [
  [-9, -9, -9, 1, 1, 1,],
  [0, -9, 0, 4, 3, 2,],
  [-9, -9, -9, 1, 2, 3,],
  [0, 0, 8, 6, 6, 0,],
  [0, 0, 0, -2, 0, 0,],
  [0, 0, 1, 2, 4, 0,],
];

function maxBrick(test){
  // helper sum function
  const sum = (arr) => arr.reduce((s, n) => s   n)
  let max 

  for (let row = 0; row < test.length - 2; row   ){
    for(let col = 0; col < test[row].length - 2; col  ){
      // slice out "brick"
      let brick = test          
                  .slice(row, row 3)
                  .map(r => r.slice(col, col 3))

      // get bricks hourglass sum
      let curr_sum = sum([
                      sum(brick[0]),
                      brick[1][1], 
                      sum(brick[2]) 
                    ])
      // set max if bigger
      if (max === undefined || curr_sum > max) max = curr_sum
    }
  }
  return max
}

console.log(maxBrick(test))  

Комментарии:

1. большое спасибо за ваш ответ… код сработал …. ваши предложения действительно полезны для меня

Ответ №4:

Ошибки в getSubArray :

  • Индекс во внутреннем цикле неверен. Это должно быть tlc[1] вместо tlc[0]
  • Вы намереваетесь удалить 2 элемента во второй строке, но:
    • Это не должно происходить во внутреннем цикле
    • Это противоречит общему характеру функции. Подумайте, что это делает, когда размер равен 2 или 8? Возможно, вы могли бы выполнить такое удаление во всех строках, кроме первой и последней. Этот способ остается несколько общим
    • b[i] это не массив, поэтому вызов pop or shift на нем не будет работать
    • i является индексом в arr , нет b , поэтому b[i] вы укажете на неправильный или даже несуществующий элемент. Вы должны просто применить pop и shift к b себе.

Вот исправленная функция:

 function getSubArray(arr, tlc, size) {
  var a = new Array();
  for (var i = tlc[0]; i < size   tlc[0]; i  ) {
    var b = new Array();
    for (var j = tlc[1]; j < size   tlc[1]; j  ) { // index must be 1
      b.push(arr[i][j]);
    }
    if ((i - tlc[0]) % (size-1)) { // A bit more generic; out of inner loop
      b.pop(); // No index
      b.shift();
    }
    a.push(b);
  }
  console.log(a);
  return a;
}
  

Есть еще что сказать о вашем коде:

  • Использование eval не выполнено. Это также влияет на производительность. Чтобы суммировать значения в массиве, вы должны использовать встроенный reduce метод: a.reduce((b, c) => b c, 0)
  • В JavaScript недавно появились такие методы массива, как .flat() , которые с соответствующим аргументом могут делать то, что ravel делает
  • JavaScript имеет Array.isArray , что делает ваш собственный isArray ненужным
  • Вам не нужно вызывать Array конструктор. Просто используйте литерал: []

Комментарии:

1. @trincot … большое спасибо за ваш ответ… код сработал… ваши предложения действительно полезны для меня

2. Да, я подумал, давайте ответим на вопрос «можете ли вы помочь мне разобраться с ошибками?» … Не уверен, почему вы приняли ответ, который не ответил на этот вопрос;-P