#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
orshift
на нем не будет работать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