Estoy tratando de escribir una función que haga lo siguiente:
- toma una matriz de enteros como argumento (por ejemplo, [1,2,3,4])
- crea una matriz de todas las permutaciones posibles de [1,2,3,4], con cada permutación con una longitud de 4
la función a continuación (la encontré en línea) hace esto tomando una cadena como argumento y devolviendo todas las permutaciones de esa cadena
No pude descubrir cómo modificarlo para que funcione con una variedad de enteros (creo que esto tiene algo que ver con la forma en que algunos de los métodos funcionan de manera diferente en cadenas que en enteros, pero no estoy seguro. ..)
var permArr = [], usedChars = [];
function permute(input) {
var i, ch, chars = input.split("");
for (i = 0; i < chars.length; i++) {
ch = chars.splice(i, 1);
usedChars.push(ch);
if (chars.length == 0)
permArr[permArr.length] = usedChars.join("");
permute(chars.join(""));
chars.splice(i, 0, ch);
usedChars.pop();
}
return permArr
};
Nota: Estoy buscando hacer que la función devuelva matrices de enteros , no una matriz de cadenas .
Realmente necesito la solución para estar en JavaScript. Ya he descubierto cómo hacer esto en Python
fuente
Poco tarde, pero me gusta agregar una versión un poco más elegante aquí. Puede ser cualquier conjunto ...
Agregar una versión ES6 (2015). Tampoco muta la matriz de entrada original. Funciona en la consola en Chrome ...
Entonces...
Rendimientos ...
Y...
Rendimientos ...
fuente
var results = new Array(factorial(inputArr.length)), length=0
, luego reemplácelaresults.push(…)
conresults[length++]=…
var cur, memo = memo || [];
?slice()
depermute(curr.slice(), m.concat(next))
realmente necesario?El siguiente algoritmo muy eficiente utiliza el método de Heap para generar todas las permutaciones de N elementos con complejidad de tiempo de ejecución en O (N!):
El mismo algoritmo implementado como generador con complejidad espacial en O (N):
Mostrar fragmento de código
Comparación de rendimiento
Siéntase libre de agregar su implementación al siguiente conjunto de pruebas benchmark.js :
Mostrar fragmento de código
Resultados en tiempo de ejecución para Chrome 48:
fuente
yield permutation.slice()
si no corta, solo se calcula la última permutación.fuente
.filter(uniq)
en el resultado.[1,2,3].length == 3 && "foo" || "bar"
o[1,2].length == 3 && "foo" || "bar"
oh my! ¡Ahi esta!(or (and (= 3 2) (print "hello!")) (print "goodbye"))
He mejorado la respuesta de SiGanteng .
Ahora es posible llamar
permute
más de una vez, porquepermArr
yusedChars
se borran cada vez.Mostrar fragmento de código
fuente
La siguiente función permuta una matriz de cualquier tipo y llama a una función de devolución de llamada específica en cada permutación encontrada:
Si lo llamas así:
Creo que hará exactamente lo que necesita: llenar una matriz llamada
result
con las permutaciones de la matriz [1, 2, 3]. El resultado es:Código ligeramente más claro en JSFiddle: http://jsfiddle.net/MgmMg/6/
fuente
La mayoría de las respuestas a esta pregunta utilizan operaciones costosas como inserciones y eliminaciones continuas de elementos en una matriz, o copiar matrices reiteradamente.
En cambio, esta es la solución típica de retroceso:
Dado que la matriz de resultados será enorme, podría ser una buena idea iterar los resultados uno por uno en lugar de asignar todos los datos simultáneamente. En ES6, esto se puede hacer con generadores:
fuente
Esta es una tarea interesante y aquí está mi contribución. Es muy simple y rápido. Si está interesado, tenga paciencia conmigo y siga leyendo.
Si desea realizar este trabajo rápidamente, definitivamente debe dedicarse a la programación dinámica. Lo que significa que debes olvidarte de los enfoques recursivos. Eso es seguro...
OK, el código de le_m que usa el método Heap parece ser el más rápido hasta ahora. Bueno, no tengo un nombre para mi algoritmo, no sé si ya se implementó o no, pero es muy simple y rápido. Como con todos los enfoques de programación dinámica, comenzaremos con el problema más simple e iremos al resultado final.
Suponiendo que tenemos una variedad de
a = [1,2,3]
, comenzaremos conLuego siga estos tres pasos;
r
matriz (resultado) agregaremos el siguiente elemento de la matriz de entrada.t
. (bueno, excepto el primero para no perder el tiempo con 0 rotación)r
la matriz provisional,t
deberíamos tener el siguiente nivel de resultados, así que hacemosr = t; t = [];
y continuamos hasta la longitud de la matriz de entradaa
.Entonces los siguientes son nuestros pasos;
Entonces aquí está el código
En pruebas múltiples, lo he visto resolver las 120 permutaciones de [0,1,2,3,4] durante 2000 veces en 25 ~ 35 ms.
fuente
rotatePerm
(el anterior) es consistentemente 1.2 más rápido. Con FF no hay consistencia. Después de varias pruebas, a vecesheapPerm
es 2 veces más rápido, algunas vecesrotatePerm
es 1,1 veces más rápido. Con otros navegadores de kits web como Opera o Epiphany,rotatePerm
resulta ser 1.1 veces más rápido. Sin embargo, con EdgeheapPerm
es constantemente 1.2 veces más rápido cada vez.permutations
función estándar :)Alguna versión inspirada de Haskell:
fuente
Responda sin la necesidad de una matriz exterior o función adicional
fuente
La versión más rápida, más efectiva (recursos) y más elegante hoy en día (2020)
fuente
len % 2 // parity dependent adjacent elements swap
significa y por qué se usa?Aquí hay una solución genial
fuente
Aquí hay otra solución "más recursiva".
Salida:
fuente
Pruébalo con:
fuente
La mayoría de las otras respuestas no utilizan las nuevas funciones del generador de JavaScript, que es una solución perfecta para este tipo de problema. Probablemente solo necesite una permutación a la vez en la memoria. Además, prefiero generar una permutación de una gama de índices, ya que esto me permite indexar cada permutación y saltar directamente a cualquier permutación en particular, así como ser utilizada para permutar cualquier otra colección.
fuente
fuente
Aquí hay uno que hice ...
¡Y aquí está otra vez, pero menos escrito!
Cómo funciona: si la matriz es más larga que un elemento, recorre cada elemento y lo concatena con una llamada recursiva a sí mismo con los elementos restantes como argumento. No muta la matriz original.
fuente
Respuesta funcional usando flatMap:
fuente
Produce permutaciones ordenadas lexicográficamente. Funciona solo con números. En otro caso, debe cambiar el método de intercambio en la línea 34.
fuente
Similar en espíritu a la solución de estilo Haskell de @crl, pero trabajando con
reduce
:fuente
Este es un caso de uso muy bueno para map / reduce:
[].concat(cv,a)
fuente
Aquí hay una versión mínima de ES6. El aplanamiento y sin funciones se pueden extraer de Lodash.
Resultado:
fuente
fuente
fuente
Un poco tarde. Todavía por si acaso si esto ayuda a alguien.
fuente
Tuve una grieta al hacer una versión de esto que intenta ser concisa pero legible, y una programación puramente funcional.
Tenga en cuenta que el formato del argumento convierte una cadena de entrada en una matriz. No estoy seguro si eso es demasiado mágico ... No estoy seguro de haberlo visto en la naturaleza. Para una legibilidad real, probablemente lo haría
input = [...input]
para la primera línea de la función.fuente
Esta es una implementación del algoritmo de Heap (similar a @ le_m's), excepto que es recursivo.
Parece que también es bastante más rápido: https://jsfiddle.net/3brqzaLe/
fuente
Mi primera contribución al sitio. Además, según las pruebas que he realizado, este código se ejecuta más rápido que todos los otros métodos mencionados aquí antes de esta fecha, por supuesto, es mínimo si hay pocos valores, pero el tiempo aumenta exponencialmente cuando se agregan demasiados.
fuente
Escribí una publicación para demostrar cómo permutar una matriz en JavaScript. Aquí está el código que hace esto.
Solo llama
trabajará. Para obtener detalles sobre cómo funciona esto, consulte la explicación en esa publicación.
fuente
fuente