Je recherche un algorithme qui génère toutes les permutations de partitions de longueur fixe d'un entier. L'ordre n'a pas d'importance.
Par exemple, pour N = 4 et longueur L = 3: P>
[(0, 2, 2), (2, 0, 2), (2, 2, 0), (2, 1, 1), (1, 2, 1), (1, 1, 2), (0, 1, 3), (0, 3, 1), (3, 0, 1), (3, 1, 0), (1, 3, 0), (1, 0, 3), (0, 0, 4), (4, 0, 0), (0, 4, 0)]
6 Réponses :
D'accord. Tout d'abord, oubliez les permutations et générez simplement les partitions de la longueur L (comme suggéré par @svein Bringli). Notez que pour chaque partition, vous pouvez imposer une commande sur les éléments, tels que>. Maintenant, juste "compter", maintenir votre commande. Pour n = 4, k = 3: Alors, comment implémenter cela? On dirait: tout en soustrayant 1 de la position I et de l'ajout à la position suivante maintient notre commande, soustrayez 1 de la position I, ajoutez 1 à la position I + 1 et passez à la position suivante. Si nous sommes dans la dernière position, étachez-vous. P> Voici un petit python qui ne fait que: p> Vous avez maintenant une liste de listes (Vraiment une liste de multisets) et générer toutes les permutations de chaque multiset de la liste vous donne votre solution. Je ne vais pas entrer dans cela, il y a un algorithme récursif qui dit essentiellement, pour chaque position, choisissez chaque élément unique dans le multiviseur et ajoute les permutations de la multi-utilisée résultant de l'élimination de cet élément de la multiset. P> P> P >
J'ai essayé de courir cette solution et cela n'a pas fonctionné pour moi pour la plupart des cas; Il a fait n = 4 & L = 3, mais peu d'autres. J'ai besoin d'un algorithme pour le sous-ensemble où n = L, et cet algorithme n'a pas produit la solution (1,1,1, ...) pour tout cas sauf n = 2. J'ai essayé de le faire travailler, mais j'ai finalement dû faire une nouvelle solution (ci-dessous).
Étant donné que vous posez cette question à l'extérieur, vous seriez probablement intéressé une réponse autorisée! On peut le trouver dans "7.2.1.2 - générer toutes les permutations" de Knuth's l'art de la programmation informatique em> ( En outre, 3 algorithmes de béton peuvent être trouvés ici . p>
Entendre entendre! Si vous êtes dans ce type de problèmes, cette sous-volume contient de nombreuses variantes. Les solutions Knuth propose un festin pour l'esprit: très élégant et intelligent.
Comme je l'ai mentionné ci-dessus, je ne pouvais pas obtenir le code de Rlibby pour travailler pour mes besoins et j'avais besoin de code où N = L, donc un sous-ensemble de vos besoins. Voici mon code ci-dessous, en C #. Je sais que ce n'est pas parfaitement une réponse à la question ci-dessus, mais je crois que vous devrez seulement modifier la première méthode pour le faire fonctionner pour différentes valeurs de L; Ajoutez fondamentalement le même code @RLIBBY a fait, rendant le tableau de longueur l au lieu de longueur n.
public static List<int[]> GetPartitionPermutations(int n) { int[] l = new int[n]; var results = new List<int[]>(); GeneratePermutations(l, n, n, 0, results); return results; } private static void GeneratePermutations(int[] l, int n, int nMax, int i, List<int[]> results) { if (n == 0) { for (; i < l.Length; ++i) { l[i] = 0; } results.Add(l.ToArray()); return; } for (int cnt = Math.Min(nMax, n); cnt > 0; --cnt) { l[i] = cnt; GeneratePermutations(l, (n - cnt), cnt, i + 1, results); } }
Comme indiqué par @pbarranis, le code de @rlibby n'inclut pas toutes les listes lorsque n em> est égal k em>. Vous trouverez ci-dessous un code Python qui inclut toutes les listes. Ce code n'est pas récursif, qui peut être plus efficace en ce qui concerne l'utilisation de la mémoire. Les listes sont créées dans l'ordre colexicographique (algorithme et plus de description ici ). P> P>
Beaucoup de recherches ont conduit à cette question. Voici une réponse qui inclut les permutations: par exemple, All_Part (4, 3) comme demandé par op donne: p> [[0, 0, 4],
[0, 1, 3],
[0, 2, 2],
[0, 3, 1],
[0, 4, 0],
[1, 0, 3],
[1, 1, 2],
[1, 2, 1],
[1, 3, 0],
[2, 0, 2],
[2, 1, 1],
[2, 2, 0],
[3, 0, 1],
[3, 1, 0],
[4, 0, 0]]
J'ai constaté que l'utilisation d'une fonction récursive n'était pas bonne pour les plus grandes longueurs et les entiers, car il mâche trop de RAM et en utilisant une fonction génératrice / résolution (que "les valeurs" des rendements ") était trop lente et nécessitait une grande bibliothèque pour Faites-le en plate-forme croisée.
Voici une solution où j'ai écrit faire quelque chose avec "partition" ici. em> est l'endroit où vous le feriez consommez effectivement la valeur. (Dans la dernière itération, le code continuera d'exécuter le reste de la boucle, mais j'ai trouvé que ceci soit mieux que de vérifier constamment les conditions de sortie - elle est optimisée pour les opérations plus importantes) P>
#include <vector> // for std::vector
#include <numeric> // for std::accumulate
#include <algorithm> // for std::next_permutation and std::max
using namespace std;
Ne devrait-il pas être permutations de (2, 1, 1) être dans cette liste?
Je savais que j'ai oublié quelque chose. Merci, ajouté.
Les permutations des partitions entier sont appelées "compositions".
Serait-il plus simple de générer d'abord toutes les permutations commandées (4,0,0), (3,1,0), (2,2,0), (2,1,1), puis générer toutes les permutations de celles-ci?
Vous dites que cet ordre n'a pas d'importance, mais votre réponse a des entrées identiques, à l'exception de la commande. Quelle partie est fausse?