Me gustaría obtener la salida de la entrada.
Debería ser un elemento empujado como perseguir colas y no podría duplicarse.
La regla es muy simple. En primer lugar, si hay el mismo elemento con entrada[0][1] en entrada[i][0], puede poner el primer valor del elemento en un resultado.
El elemento es [1,5], por lo que el resultado se convierte en [[0,1]].
Ahora solo puedes repetir. El primer elemento de [5,29] es el mismo elemento con [1,5][1] y el resultado se convierte en [[0,1,5]]
He sido muy frustrante durante algunas semanas para resolver este problema. Por favor ayuda. Cualquier comentario será bienvenido.
input = [ [ 0, 1 ], [ 0, 2 ], [ 0, 3 ], [ 0, 4 ], [ 1, 5 ], [ 2, 6 ], [ 3, 7 ], [ 4, 10 ], [ 4, 11 ], [ 4, 12 ], [ 4, 13 ], [ 5, 29 ], [ 6, 29 ], [ 7, 8 ], [ 8, 29 ], [ 9, 29 ], [ 12, 18 ], [ 13, 19 ], [ 17, 29 ], [ 18, 29 ], [ 19, 29 ], [ 21, 29 ], [ 24, 29 ], [ 26, 29 ], [ 28, 29 ] ] output = [ [0,1,5,29],[0,2,6,29],[0,3,7,8,29],[0,4,10],[0,4,11], [0,4,12,18,29],[0,4,13,19,29] ]Puede escribir solver como un generador con una entrada de t y una consulta inicial de q . Otras respuestas sugieren remodelar su entrada u otras técnicas funcionales que iteran sobre la entrada varias veces. Esta técnica simple de estilo imperativo utiliza solo una pasada (por llamada recursiva). El uso de un generador le permite encontrar todas las soluciones, pero se puede pausar/detener en cualquier momento, por cualquier otro motivo:
function* solver (t, q) { let atLeastOnce = false for (const [parent, child] of t) { if (parent == q) { atLeastOnce = true for (const sln of solver(t, child)) yield [parent, ...sln] } } if (!atLeastOnce) { yield [q] } } const input = [[0,1],[0,2],[0,3],[0,4],[1,5],[2,6],[3,7],[4,10],[4,11],[4,12],[4,13],[5,29],[6,29],[7,8],[8,29],[9,29],[12,18],[13,19],[17,29],[18,29],[19,29],[21,29],[24,29],[26,29],[28,29]] for (const sln of solver(input, 0)) console.log(JSON.stringify(sln)) [0,1,5,29] [0,2,6,29] [0,3,7,8,29] [0,4,10] [0,4,11] [0,4,12,18,29] [0,4,13,19,29] Los generadores son iterables , por lo que puede recopilar todos los resultados en una matriz utilizando Array.from -
const all = Array.from(solver(input, 0)) console.log(all) [ [0,1,5,29], [0,2,6,29], [0,3,7,8,29], [0,4,10], [0,4,11], [0,4,12,18,29], [0,4,13,19,29], ]Combine generadores con un tipo de entrada optimizado para obtener resultados aún mejores.
Basado en cómo entendí tu salida, lo que quieres es como una cadena de dominó. Siembra la salida con matrices que contienen 0 en el primer elemento, por ejemplo, [0,1] y [0,2] ..., y luego simplemente encuentra la siguiente matriz para unirse a la cadena en función del último elemento en el array vs el primer elemento en la siguiente entrada.
Este proceso es de naturaleza recursiva , ya que comienza con las semillas y no tiene idea de qué tan lejos/profundo necesitará unirse. Para desglosar esto, podemos hacer esto:
input en semillas y no semillas (nodos).La función debería invocarse a sí misma recursivamente, y aquí hay una lógica rápida:
/** * @method * @params arr The seed array (which will grow in length) * @params nodes The collection of non-seeds */ function chain(arr, nodes) { // We first find whatever nodes left that we can domino-chain to the current seed const nextNodes = nodes.filter(node => node[0] === arr[arr.length - 1]); // If nothing is to be found, return the array if (!nextNodes.length) return [arr]; // Otherwise we go through all the next nodes and create a copy of the current seed // And then append the next node to it return nextNodes.map(nextNode => { return chain([...arr, nextNode[1]], nodes); }).flat(); }Vea la prueba de concepto a continuación:
const input = [ [0, 1], [0, 2], [0, 3], [0, 4], [1, 5], [2, 6], [3, 7], [4, 10], [4, 11], [4, 12], [4, 13], [5, 29], [6, 29], [7, 8], [8, 29], [9, 29], [12, 18], [13, 19], [17, 29], [18, 29], [19, 29], [21, 29], [24, 29], [26, 29], [28, 29] ]; const seeds = input.filter(entry => entry[0] === 0); const nodes = input.filter(entry => entry[0] !== 0); function chain(arr, nodes) { const nextNodes = nodes.filter(node => node[0] === arr[arr.length - 1]); if (!nextNodes.length) return [arr]; return nextNodes.map(nextNode => { return chain([...arr, nextNode[1]], nodes); }).flat(); } const output = seeds.map(seed => { return chain(seed, nodes); }).flat(); console.log(output);Dividiría el problema en 2:
Aquí hay una implementación de ese enfoque:
const input = [ [ 0, 1 ], [ 0, 2 ], [ 0, 3 ], [ 0, 4 ], [ 1, 5 ], [ 2, 6 ], [ 3, 7 ], [ 4, 10 ], [ 4, 11 ], [ 4, 12 ], [ 4, 13 ], [ 5, 29 ], [ 6, 29 ], [ 7, 8 ], [ 8, 29 ], [ 9, 29 ], [ 12, 18 ], [ 13, 19 ], [ 17, 29 ], [ 18, 29 ], [ 19, 29 ], [ 21, 29 ], [ 24, 29 ], [ 26, 29 ], [ 28, 29 ] ]; const nodes = {}; // Store all paths between nodes for (const [ start, end ] of input) { nodes[end] = nodes[end] || { id: end, children: [] }; nodes[start] = nodes[start] || { id: start, children: [] }; nodes[start].children.push(nodes[end]); } // Find all paths from 0 const getPaths = ({ children, id }) => children.length === 0 ? [[ id ]] : children.flatMap( n => getPaths(n).map(p => [ id, ...p ]) ) console.log(getPaths(nodes[0]));