Cómo generar una matriz de valores incrementales a partir de una matriz determinada
la idea es crear una especie de forma de diamante donde las matrices comiencen a disminuir de tamaño una vez que lleguen a la mitad de la matriz. En otras palabras, la matriz más larga será la que contenga el valor medio de la matriz o (array.length/2 + 1)
y en los casos en que los elementos sean cortos para completar la matriz en la segunda mitad, simplemente reemplácelos con 'E' para indicar un espacio vacío como en el segundo ejemplo.
example 1 var array = ['a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p'] //the longest array in length is containing 'i' which is the value at array.length/2 + 1 var output = [ ['a'], ['b','c'], ['d','e','f'], ['g','h','i','j'], ['k','l','m'], ['n','o'], ['p'] ] example 2 var array = ['a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t'] enter code here //the longest array in length is containing 'k' which is the value at array.length/2 + 1 var output = [ ['a'], ['b','c'], ['d','e','f'], ['g','h','i','j'], ['k','l','m','n','o'], ['p','q','r','s'], ['t','E','E'], ['E','E'], ['E] ]Aquí está el código que he probado:
const values = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16]; const halfLen = values.length/2 + 1; var topArr = []; for(let i = 0; i < values.length; i ++) { if(i <= halfLen) { topArr.push(values[i]) } } console.log(topArr) var filTopArr = []; for(let i = 0; i <= topArr.length; i ++) { let prevIndex = i - 1; if(i === 0) { filTopArr.push(topArr[i]) } else if(i === 1) { filTopArr.push(topArr.slice(i, i + i + 1)) } else { filTopArr.push(topArr.slice(i, i + i )) } } console.log(filTopArr)mi idea aquí era separar la matriz en dos matrices diferentes, que serán la parte superior que aumentará de tamaño y la segunda parte inferior que disminuirá de tamaño.
El código anterior tenía esta salida
[1, [2, 3], [3, 4], [4, 5, 6], [5, 6, 7, 8], [6, 7, 8, 9], [7, 8, 9], [8, 9], [9], []]Algunas observaciones:
El número de cadenas en la salida (incluidas las cadenas "E" de relleno) es siempre un cuadrado perfecto (1, 4, 9, 16, 25, etc.)
Para saber cuántas cadenas "E" se deben agregar, necesitamos saber cuál es el mínimo cuadrado perfecto que no es menor que el tamaño de entrada.
El subarreglo más largo (medio) en la salida tiene un tamaño que es la raíz cuadrada de ese cuadrado perfecto.
El número de subarreglos es el doble de ese número menos 1.
Esto conduce a la siguiente implementación:
function diamond(array) { // Get least perfect square that is not less than the array length const sqrt = Math.ceil(Math.sqrt(array.length)); const size = sqrt ** 2; // Pad the array with "E" strings so to reach that perfect square size const all = [...array, ..."E".repeat(size - array.length)]; const length = 2 * sqrt; return Array.from({length}, (_, width) => { return all.splice(0, Math.min(width, length - width)); }).slice(1); // Skip the first subarray that was produced (empty array) } // Demo using the two provided examples: var array = ['a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p']; console.log(diamond(array)); var array = ['a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t']; console.log(diamond(array));Aquí hay una versión recursiva. Tenga en cuenta que la display es solo para fines de presentación. El único trabajo real está en diamond :
const diamond = (xs, [len = xs.length, up = true, n = 1] = []) => n == 0 ? [] : [ Object .assign (Array (n) .fill ('E'), xs .slice (0, n)), ...diamond (xs .slice (n), up && n * n < len ? [len, true, n + 1] : [len, false, n - 1]) ] const display = (xss) => console .log (`${xss .map ( (xs, i) => `${' '.repeat (Math .abs ((xss .length - 1) / 2 - i) + 1)}${xs .join (' ') }`) .join ('\n')}`) const demos = [ ['a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p'], ['a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u'], [1, 2, 3, 4, 5, 6, 7, 8] ] demos .forEach (array => display (diamond (array))) .as-console-wrapper {max-height: 100% !important; top: 0} Realizamos un seguimiento de la longitud de la cadena actual ( n , por defecto es 1 ), la longitud de la matriz original ( len ) y una bandera booleana para saber si nuestra longitud se mueve hacia arriba o hacia abajo ( up ). Aumentamos n en las iteraciones iniciales, agregando los siguientes n caracteres de nuestra entrada como el siguiente subarreglo. Cuando n llega a cero, devolvemos una matriz vacía. Cuando n ** n es mayor o igual que len , cambiamos up false y comenzamos a restar uno de n a partir de ese momento. La única otra necesidad es llenar nuestra matriz restante con 'E' s. Hacemos esto con una llamada Object .assign .
Si desea una salida formateada más como una forma literal de matriz, puede usar esta versión de display :
const display = (xss) => console .log (`[\n${xss .map ( (xs, i) => `${' '.repeat (Math .abs ((xss .length - 1) / 2 - i) + 1)}['${xs .join (`','`) }']`) .join ('\n')}\n]`)para obtener una salida como esta:
[ ['a'] ['b','c'] ['d','e','f'] ['g','h','i','j'] ['k','l','m','n','o'] ['p','q','r','s'] ['t','u','E'] ['E','E'] ['E'] ]Sin embargo, tenga en cuenta que esta recursividad es un poco autoritaria, con tres variables recursivas predeterminadas separadas. Sería tan probable que opte por la solución de Trincot como esta. Pero es bueno tener alternativas.