J'essaye d'écrire une fonction qui fait ce qui suit:
- prend un tableau d'entiers comme argument (par exemple [1,2,3,4])
- crée un tableau de toutes les permutations possibles de [1,2,3,4], chaque permutation ayant une longueur de 4
la fonction ci-dessous (je l'ai trouvée en ligne) le fait en prenant une chaîne comme argument et en retournant toutes les permutations de cette chaîne
Je ne pouvais pas comprendre comment le modifier pour le faire fonctionner avec un tableau d'entiers, (je pense que cela a quelque chose à voir avec la façon dont certaines des méthodes fonctionnent différemment sur les chaînes que sur les entiers, mais je ne suis pas sûr. ..)
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
};
Remarque: je cherche à faire en sorte que la fonction renvoie des tableaux d' entiers , pas un tableau de chaînes .
J'ai vraiment besoin que la solution soit en JavaScript. J'ai déjà compris comment faire cela en python
la source
Un peu tard, mais j'aime ajouter une version un peu plus élégante ici. Peut être n'importe quel tableau ...
Ajout d'une version ES6 (2015). Ne modifie pas non plus le tableau d'entrée d'origine. Fonctionne dans la console dans Chrome ...
Alors...
Rendements ...
Et...
Rendements ...
la source
var results = new Array(factorial(inputArr.length)), length=0
, puis la remplacerresults.push(…)
parresults[length++]=…
var cur, memo = memo || [];
?slice()
danspermute(curr.slice(), m.concat(next))
vraiment nécessaire?L'algorithme très efficace suivant utilise la méthode de Heap pour générer toutes les permutations de N éléments avec une complexité d'exécution en O (N!):
Le même algorithme implémenté en générateur avec complexité spatiale en O (N):
Afficher l'extrait de code
Comparaison des performances
N'hésitez pas à ajouter votre implémentation aux éléments suivants tests benchmark.js :
Afficher l'extrait de code
Résultats d'exécution pour Chrome 48:
la source
yield permutation.slice()
si vous ne découpez pas, vous n'obtiendrez que la dernière permutation calculée.la source
.filter(uniq)
sur le résultat.[1,2,3].length == 3 && "foo" || "bar"
ou[1,2].length == 3 && "foo" || "bar"
oh mon Dieu! il y a!(or (and (= 3 2) (print "hello!")) (print "goodbye"))
J'ai amélioré la réponse de SiGanteng .
Maintenant, il est possible d'appeler
permute
plus d'une fois, carpermArr
etusedChars
sont effacés à chaque fois.Afficher l'extrait de code
la source
La fonction suivante permute un tableau de n'importe quel type et appelle une fonction de rappel spécifiée sur chaque permutation trouvée:
Si vous l'appelez comme ceci:
Je pense qu'il fera exactement ce dont vous avez besoin - remplir un tableau appelé
result
avec les permutations du tableau [1, 2, 3]. Le résultat est:Code un peu plus clair sur JSFiddle: http://jsfiddle.net/MgmMg/6/
la source
La plupart des réponses à cette question utilisent des opérations coûteuses telles que les insertions et les suppressions continues d'éléments dans un tableau, ou la copie de tableaux de manière répétitive.
Au lieu de cela, c'est la solution de retour en arrière typique:
Étant donné que le tableau de résultats sera énorme, il peut être judicieux d'itérer les résultats un par un au lieu d'allouer toutes les données simultanément. Dans ES6, cela peut être fait avec des générateurs:
la source
C'est une tâche intéressante et voici ma contribution. C'est très simple et rapide. Si vous êtes intéressé, veuillez rester avec moi et continuer à lire.
Si vous souhaitez effectuer ce travail rapidement, vous devez absolument vous lancer dans la programmation dynamique. Ce qui signifie que vous devez oublier les approches récursives. Ça c'est sûr...
OK le code de le_m qui utilise la méthode de Heap semble être le plus rapide à ce jour. Eh bien, je n'ai pas de nom pour mon algorithme, je ne sais pas s'il a déjà été implémenté ou non mais c'est très simple et rapide. Comme pour toutes les approches de programmation dynamique, nous allons commencer par le problème le plus simple et aller pour le résultat final.
En supposant que nous avons un tableau de
a = [1,2,3]
nous commencerons parSuivez ensuite ces trois étapes;
r
tableau (résultat), nous ajouterons l'élément suivant du tableau d'entrée.t
. (enfin sauf pour le premier pour ne pas perdre de temps avec 0 rotation)r
tableau intermédiaire, noust
devrions contenir le niveau de résultats suivant, donc nous faisonsr = t; t = [];
et continuons jusqu'à la longueur du tableau d'entréea
.Voici donc nos étapes;
Alors voici le code
Dans plusieurs tests, je l'ai vu résoudre les 120 permutations de [0,1,2,3,4] pour 2000 fois en 25 ~ 35ms.
la source
rotatePerm
(celui ci-dessus), c'est toujours 1,2 plus rapide. Avec FF, il n'y a pas de cohérence. Après plusieurs tests, c'est parfoisheapPerm
2 fois plus rapide, parfoisrotatePerm
1,1 fois plus rapide. Avec d'autres navigateurs de kit Web tels que Opera ou Epiphany, ilrotatePerm
s'avère toujours 1,1 fois plus rapide. Cependant, avec Edge,heapPerm
c'est toujours 1,2 fois plus rapide à chaque fois.permutations
fonction standard :)Une version inspirée de Haskell:
la source
Répondez sans avoir besoin d'un tableau extérieur ou d'une fonction supplémentaire
la source
La version la plus rapide, la plus efficace et la plus élégante de nos jours (2020)
la source
len % 2 // parity dependent adjacent elements swap
signifie et pourquoi est-il utilisé?Voici une solution cool
la source
Voici une autre solution "plus récursive".
Production:
la source
Testez-le avec:
la source
La plupart des autres réponses n'utilisent pas les nouvelles fonctions du générateur javascript qui est une solution parfaite à ce type de problème. Vous n'avez probablement besoin que d'une permutation à la fois en mémoire. De plus, je préfère générer une permutation d'une plage d'indices car cela me permet d'indexer chaque permutation et de passer directement à une permutation particulière ainsi que d'être utilisé pour permuter toute autre collection.
la source
la source
En voici un que j'ai fait ...
Et le voici encore mais écrit moins laconiquement! ...
Comment cela fonctionne: Si le tableau est plus long qu'un élément, il parcourt chaque élément et le concatène avec un appel récursif à lui-même avec les éléments restants comme argument. Il ne mute pas le tableau d'origine.
la source
Réponse fonctionnelle avec flatMap:
la source
Produit des permutations ordonnées lexicographiquement. Fonctionne uniquement avec des nombres. Dans les autres cas, vous devez changer la méthode de swap à la ligne 34.
la source
Similaire dans l'esprit à la solution de style Haskell de @crl, mais fonctionnant avec
reduce
:la source
C'est un très bon cas d'utilisation de map / reduction:
[].concat(cv,a)
la source
Voici une version ES6 minimale. Les fonctions aplatir et sans fonctions peuvent être extraites de Lodash.
Résultat:
la source
la source
la source
Assez tard. Toujours juste au cas où cela aiderait quelqu'un.
la source
J'ai eu une fissure à faire une version de ceci qui tente d'être une programmation concise mais lisible et purement fonctionnelle.
Notez que la mise en forme de l'argument transforme une chaîne d'entrée en un tableau. Je ne sais pas si c'est un peu trop magique ... Je ne sais pas si je l'ai vu dans la nature. Pour une réelle lisibilité, je le ferais probablement plutôt
input = [...input]
pour la première ligne de la fonction.la source
Il s'agit d'une implémentation de l'algorithme de Heap (similaire à @ le_m), sauf qu'il est récursif.
On dirait que c'est aussi assez rapide: https://jsfiddle.net/3brqzaLe/
la source
Ma première contribution au site. De plus, d'après les tests que j'ai effectués, ce code tourne plus vite que toutes les autres méthodes mentionnées ici avant cette date, bien sûr il est minime s'il y a peu de valeurs, mais le temps augmente de façon exponentielle lorsqu'on en ajoute trop.
la source
J'ai écrit un article pour montrer comment permuter un tableau en JavaScript. Voici le code qui fait cela.
Il suffit d'appeler
marchera. Pour plus de détails sur la façon dont cela fonctionne, veuillez vous référer à l'explication dans ce post.
la source
la source