Générer la liste de toutes les permutations possibles d'une chaîne

Comment puis-je générer une liste de toutes les permutations possibles d'une chaîne entre x et y caractères de longueur, contenant une liste variable de caractères.

N'importe quel langage fonctionnerait, mais il devrait être portable.

请先 登录 后评论

5 réponses

alumb

Il existe plusieurs façons de procéder. Les méthodes courantes utilisent la récursivité, la mémorisation ou la programmation dynamique. L'idée de base est que vous produisez une liste de toutes les chaînes de longueur 1, puis à chaque itération, pour toutes les chaînes produites lors de la dernière itération, ajoutez cette chaîne concaténée avec chaque caractère de la chaîne individuellement. (l'index de la variable dans le code ci-dessous garde une trace du début de la dernière et de la prochaine itération)

Un pseudo-code :

list = originalString.split('')
index = (0,0)
list = ["]
for iteration n in 1 to y:
  index = (index[1], len(list))
  for string s in list.subset(index[0] to end):
    for character c in originalString:
      list.add(s + c)

vous devrez alors supprimer toutes les chaînes de moins de x de longueur, ce seront les premières entrées (x-1) * len(originalString) de la liste.

请先 登录 后评论
Mike Stone

Je viens de préparer ça rapidement dans Ruby :

def perms(x, y, possible_characters)
  all = ["]
  current_array = all.clone
  1.upto(y) { |iteration|
    next_array = []
    current_array.each { |string|
      possible_characters.each { |c|
        value = string + c
        next_array.insert next_array.length, value
        all.insert all.length, value
      }
    }
    current_array = next_array
  }
  all.delete_if { |string| string.length < x }
end

Vous pourriez vous pencher sur l'API de langage pour les fonctions de type permutation intégrées, et vous pourriez être en mesure d'écrire un code plus optimisé, mais si les nombres sont si élevés, je ne suis pas sûr qu'il y ait beaucoup de solution pour avoir un beaucoup de résultats.

Quoi qu'il en soit, l'idée derrière le code est de commencer avec une chaîne de longueur 0, puis de garder une trace de toutes les chaînes de longueur Z où Z est la taille actuelle dans l'itération. Ensuite, parcourez chaque chaîne et ajoutez chaque caractère à chaque chaîne. Enfin, à la fin, supprimez tous ceux qui étaient en dessous du seuil x et renvoyez le résultat.

Je ne l'ai pas testé avec des entrées potentiellement dénuées de sens (liste de caractères nulle, valeurs bizarres de x et y, etc.).

请先 登录 后评论
Brian Willis

Je ne sais pas pourquoi vous voudriez faire cela en premier lieu. L'ensemble résultant pour toutes les valeurs modérément élevées de x et y sera énorme et augmentera de façon exponentielle à mesure que x et/ou y grossissent.

Disons que votre ensemble de caractères possibles est les 26 lettres minuscules de l'alphabet, et que vous demandez à votre application de générer toutes les permutations où longueur = 5. En supposant que vous ne manquez pas de mémoire, vous obtiendrez 11 881 376 (c'est-à-dire 26 à la puissance 5) cordes en arrière. Augmentez cette longueur jusqu'à 6, et vous obtiendrez 308 915 776 cordes en retour. Ces chiffres deviennent douloureusement élevés, très rapidement.

Voici une solution que j'ai mise en place en Java. Vous devrez fournir deux arguments d'exécution (correspondant à x et y). Amusez-vous bien.

public class GeneratePermutations {
    public static void main(String[] args) {
        int lower = Integer.parseInt(args[0]);
        int upper = Integer.parseInt(args[1]);

        if (upper < lower || upper == 0 || lower == 0) {
            System.exit(0);
        }

        for (int length = lower; length <= upper; length++) {
            generate(length, ");
        }
    }

    private static void generate(int length, String partial) {
        if (length <= 0) {
            System.out.println(partial);
        } else {
            for (char c = 'a'; c <= 'z'; c++) {
                generate(length - 1, partial + c);
            }
        }
    }
}
请先 登录 后评论
Community

Ceci est une traduction de la version Ruby de Mike, en Common Lisp :

(defun perms (x y original-string)
  (loop with all = (list ")
        with current-array = (list ")
        for iteration from 1 to y
        do (loop with next-array = nil
                 for string in current-array
                 do (loop for c across original-string
                          for value = (concatenate 'string string (string c))
                          do (push value next-array)
                             (push value all))
                    (setf current-array (reverse next-array)))
        finally (return (nreverse (delete-if #'(lambda (el) (< (length el) x)) all)))))

Et une autre version, légèrement plus courte et utilisant davantage de fonctionnalités de boucle :

(defun perms (x y original-string)
  (loop repeat y
        collect (loop for string in (or (car (last sets)) (list "))
                      append (loop for c across original-string
                                   collect (concatenate 'string string (string c)))) into sets
        finally (return (loop for set in sets
                              append (loop for el in set when (>= (length el) x) collect el)))))
请先 登录 后评论
Crackerjack

Voici un simple mot C

请先 登录 后评论
  • 9 abonnés
  • 0 favoris,538 Feuilleter
  • UnkwnTech posée à 2022-12-10 08:52