Suma de partes de una matriz-JavaScript
arrays reduce (6)
Tratando de resolver este desafío en codewars . Según el desafío, las partes de la matriz:
ls = [0, 1, 3, 6, 10]
Son
ls = [0, 1, 3, 6, 10]
ls = [1, 3, 6, 10]
ls = [3, 6, 10]
ls = [6, 10]
ls = [10]
ls = []
Y tenemos que devolver una matriz con las sumas de esas partes.
Así que mi código es el siguiente:
function partsSums(ls) {
let arrayOfSums = [];
while(ls.length > 0) {
let sum = ls.reduce((a, b) => a + b);
arrayOfSums.push(sum);
ls.shift();
}
return arrayOfSums;
}
console.log(partsSums([0, 1, 3, 6, 10]));
El problema es que quiere que agreguemos la última suma 0 cuando la matriz está vacía. Así que deberíamos estar recibiendo:
[20, 20, 19, 16, 10, 0]
En lugar de
[20, 20, 19, 16, 10]
Así que intenté esto:
function partsSums(ls) {
let arrayOfSums = [];
while(ls.length > 0) {
let sum = ls.reduce((a, b) => a + b);
arrayOfSums.push(sum);
ls.shift();
}
arrayOfSums.push(0);
return arrayOfSums;
}
console.log(partsSums([0, 1, 3, 6, 10]));
Y esto:
function partsSums(ls) {
ls.push(0);
let arrayOfSums = [];
while(ls.length > 0) {
let sum = ls.reduce((a, b) => a + b);
arrayOfSums.push(sum);
ls.shift();
}
return arrayOfSums;
}
Pero esto causó errores de tiempo de espera de ejecución en Codewars:
Tiempo de espera agotado (12000 ms)
Así que también intenté:
function partsSums(ls) {
let arrayOfSums = [];
while(ls.length > -1) {
let sum = ls.reduce((a, b) => a + b);
arrayOfSums.push(sum);
ls.shift();
}
return arrayOfSums;
}
Pero ahora esto causa un TypeError:
TypeError: Reducción de la matriz vacía sin valor inicial
No entiendo el concepto de cómo obtener 0 en la matriz cuando todos los valores se han desplazado. El desafío parece querer 0 como la "suma" final de la matriz, incluso cuando la matriz está vacía. Pero no puedes reducir una matriz vacía. ¿Qué más puedo hacer aquí?
EDITAR : Intenté agregar valor inicial al método de reducción:
function partsSums(ls) {
let arrayOfSums = [];
while(ls.length > 0) {
let sum = ls.reduce((a, b) => a + b, 0);
arrayOfSums.push(sum);
ls.shift();
}
return arrayOfSums;
}
Lamentablemente esto todavía falla la prueba básica:
espera [] que sea profundamente igual [0]
Aquí hay una cosa que podrías hacer
function partsSums(ls) {
if(!ls.length) return [0];
let prevTotal = ls.reduce((a,b) => a + b);
return [prevTotal, ...ls.map(val => prevTotal -= val)]
}
console.log(partsSums([0, 1, 3, 6, 10]));
No hay razón para calcular la suma una y otra vez. En una matriz larga, esto será muy ineficiente (O (n²)) y podría explicar sus errores de tiempo de espera. Calcule la suma al principio y luego reste cada elemento de ella en un bucle.
ls = [0, 1, 3, 6, 10]
function partsSums(ls) {
let sum = ls.reduce((sum, n) => sum + n, 0)
res = [sum]
for (let i = 1; i <= ls.length; i++){
sum -= ls[i-1]
res.push(sum )
}
return res
}
console.log(partsSums(ls))
Otra solución que pasó todas las pruebas:
function partsSums(ls) {
let result = [0],
l = ls.length - 1;
for (let i = l; i >= 0; i--) {
result.push(ls[i] + result[ l - i]);
}
return result.reverse();
}
console.log(partsSums([]));
console.log(partsSums([0, 1, 3, 6, 10]));
console.log(partsSums([1, 2, 3, 4, 5, 6]));
console.log(partsSums([744125, 935, 407, 454, 430, 90, 144, 6710213, 889, 810, 2579358]));
Podría repetir desde el final y tomar este valor más el último valor insertado del conjunto de resultados.
Este enfoque funciona con un solo bucle y sin calcular la suma máxima de antemano.
function partsSums(ls) {
var result = [0],
i = ls.length;
while (i--) {
result.unshift(ls[i] + result[0]);
}
return result;
}
console.log(partsSums([0, 1, 3, 6, 10]));
console.log(partsSums([]));
.as-console-wrapper { max-height: 100% !important; top: 0; }
Con
push
y
reverse
.
function partsSums(ls) {
var result = [0],
l = 0,
i = ls.length;
while (i--) result.push(l += ls[i]);
return result.reverse();
}
console.log(partsSums([0, 1, 3, 6, 10]));
console.log(partsSums([]));
.as-console-wrapper { max-height: 100% !important; top: 0; }
Puede usar
for
bucle con sector y cuando
i == 0
puede dividir
len + 1
que le devolverá la matriz vacía y la suma será 0.
function partsSums(arr) {
const res = [], len = arr.length
for (let i = len; i > -1; i--) {
res.push(arr.slice(-i || len + 1).reduce((a, n) => a + n, 0))
}
return res;
}
console.log(partsSums([0, 1, 3, 6, 10]));
console.log(partsSums([1, 2, 3, 4, 5, 6]));
console.log(partsSums([744125, 935, 407, 454, 430, 90, 144, 6710213, 889, 810, 2579358]));
También puede usar dos de
reduce
doble y, si no hay un elemento siguiente, presione cero.
function partsSums(arr) {
const sum = arr => arr.reduce((r, e) => r + e, 0);
return arr.reduce((r, e, i, a) => {
const res = sum(a.slice(i, a.length));
return r.concat(!a[i + 1] ? [res, 0] : res)
}, [])
}
console.log(partsSums([0, 1, 3, 6, 10]));
console.log(partsSums([1, 2, 3, 4, 5, 6]));
console.log(partsSums([744125, 935, 407, 454, 430, 90, 144, 6710213, 889, 810, 2579358]));
prueba esto con recursion
function partsSums(ls) {
let sum = ls.reduce((a, b) => a + b, 0);
return ls.length > 0 ? [sum].concat(partsSums(ls.slice(1))) : [0];
}
console.log(partsSums([0, 1, 3, 6, 10]));
console.log(partsSums([1, 2, 3, 4, 5, 6]));
console.log(partsSums([744125, 935, 407, 454, 430, 90, 144, 6710213, 889, 810, 2579358]));