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

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

Tout langage fonctionnerait, mais il devrait être portable.

0
ajouté édité
Vues: 11
ajouté l'auteur hippietrail, source

36 Réponses

@david: Both @Adam Backtrom and @Viper007Bond give some good advice so I thought I'd take their advice and see if I couldn't implement something, see below.

Ce qui suit est un plugin appelé Données WP Active Plugins qui analyse les métadonnées d'en-tête pour tous les plugins actifs à chaque fois qu'un plugin est activé et stocke toutes les métadonnées de chaque plugin dans un tableau option dans wp_options . Je l'ai conçu pour les plugins WordPress réguliers et les plugins multisites à l'échelle du site. Vous pouvez télécharger le fichier ici à partir de , mais j'ai également copié le code ici pour votre évaluation:

<?php
/*
Plugin Name: WP Active Plugins Data
Plugin URI: http://mikeschinkel.com/wordpress-plugins/wp-active-plugins-data/
Description: Loads Plugin Data on Plugin Activation and Persists to wp_options for quick retrieval.
Version: 0.1
Author: Mike Schinkel
Author URI: http://mikeschinkel.com
Note: Written for http://wordpress.stackexchange.com/questions/361/is-there-a-way-for-a-plug-in-to-get-its-own-version-number
*/

require_once(ABSPATH.'wp-admin/includes/plugin.php');

function get_active_plugin_version($plugin_path_file, $sitewide = false) {
    return get_active_plugin_attribute($plugin_path_file,'Version');
}
function get_active_plugin_attribute($plugin_path_file, $attribute) {
    $all_plugins_data = get_active_plugins_data($plugin_path_file,$sitewide);
    return (isset($all_plugins_data[$attribute]) ? $all_plugins_data[$attribute] : false);
}
function get_active_plugins_data($plugin_path_file, $sitewide = false) {
    $failsafe = false;
    $plugin = plugin_basename(trim($plugin_path_file));
    $sitewide = (is_multisite() && ( $sitewide || is_network_only_plugin($plugin)));
    if ($sitewide) {
        $all_plugins_data = get_site_option('active_sitewide_plugin_data',array());
    } else {
        $all_plugins_data = get_option('active_plugin_data',array());
    }
    if (!$failsafe && !is_array($all_plugins_data) || count($all_plugins_data)==0) {
        $failsafe = true;//Don't risk infinite recursion
        if ($sitewide) {
            $active_plugins = get_site_option('active_sitewide_plugins',array());
        } else {
            $active_plugins = get_option('active_plugins',array());
        }
        persist_active_plugin_data(null,$active_plugins,$sitewide);
        $all_plugins_data = get_active_plugin_version($plugin_path_file,$sitewide);
    }
    return $all_plugins_data[$plugin_path_file];
}
add_action('update_site_option_active_sitewide_plugins','persist_sitewide_active_plugin_data',10,2);
function persist_sitewide_active_plugin_data($option, $plugins) {
    persist_active_plugin_data(null,$plugins,'sitewide');
}
add_filter('update_option_active_plugins','persist_active_plugin_data',10,2);
function persist_active_plugin_data($old_plugins, $new_plugins, $sitewide=false) {
    $active_plugin_data = array_flip($new_plugins);
    $plugin_dir = WP_PLUGIN_DIR;
    foreach($new_plugins as $plugin) {
        $active_plugin_data[$plugin] = get_plugin_data("$plugin_dir/$plugin");
    }
    if ($sitewide)
        update_site_option('active_sitewide_plugin_data',$active_plugin_data);
    else
        update_site_option('active_plugin_data',$active_plugin_data);
}

Voulez-vous voir comment cela fonctionne? Voici un fichier de test que vous pouvez déposer à la racine de votre site WordPress ( http://example.com/test.php .) Assurez-vous que ce plugin et Akismet sont activés avant de le tester.

<?php
/*
* test.php - Place in root of WordPress website.
*
* Before running be sure to activate both Akismet and the WP Active Plugin Data plugin
*
*/

include "wp-load.php";

header('Content-type:text/plain');
$akismet = "akismet/akismet.php";
echo "Akismet Version: " . get_active_plugin_version($akismet);
echo "\n\nAkismet Description: " . get_active_plugin_attribute($akismet,'Description');
echo "\n\nAll Akismet Data:\n";
print_r(get_active_plugins_data($akismet));

Si ce n'est pas exactement ce dont vous avez besoin au moins, cela devrait vous donner un bon point de départ. J'espère que cela t'aides.

9
ajouté
+1 Beau travail, Mike. Je me demande combien de plugins sortiront de ce StackExchange. :)
ajouté l'auteur Annika Backstrom, source
Merci. En fait, j'espère beaucoup, mais j'espère aussi que seuls les meilleurs feront leur chemin dans le dépôt. Il y a trop de déchets là-haut maintenant!
ajouté l'auteur MikeSchinkel, source

Vous pouvez analyser les méta-données de votre plugin (ce truc en haut du fichier), mais c'est mieux pour les performances si vous venez de définir votre propre variable PHP avec un numéro de version correspondant. Lorsque vous mettez à jour le plugin, mettez à jour les deux numéros de version.

C'est un peu plus de travail pour vous à court terme, mais beaucoup mieux à long terme.

2
ajouté
Il peut être préférable que la performance définisse simplement une variable, mais ce n'est pas très agréable de changer le numéro de version à 2 endroits. Pour les thèmes, il existe une fonction similaire wp_get_theme qui est même utilisée dans les exemples: codex.wordpress.org/Child_Themes Cela ressemble à un mauvais design dans WordPress, il vaudrait mieux que nous puissions définir la version du plugin via une variable, puis réutiliser la variable avec les fonctions wp_enqueue_style et wp_enqueue_script.
ajouté l'auteur baptx, source

Il y a dans les écrans d'administration: get_plugin_data() . Dans les templates, je pense que vous aurez besoin du plugin pour conserver ces données en PHP, par exemple, définir une constante ou globale ou quelque chose, et garder cette valeur synchronisée avec le numéro de version de l'en-tête du plugin.

wp-settings.php calls wp_get_active_and_valid_plugins(), which pulls data from the active_plugins site option. This option only contains the path to the plugin file, and wp-settings.php only runs include_once on the file, so it's never parsed for the plugin metadata.

1
ajouté

Je viens de fouetter ç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 intéresser à l'API de langage pour les fonctions de type permutation, et vous pourriez écrire du code plus optimisé, mais si les chiffres sont si élevés, je ne suis pas sûr qu'il y ait beaucoup de résultats .

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

Je ne l'ai pas testé avec une entrée potentiellement sans signification (liste de caractères nulle, valeurs bizarres de x et y, etc.).

0
ajouté
Ce code est incorrect. Il va générer des permutations invalides, comme celles avec des caractères répétés. Par exemple, pour la chaîne "abc", il génère ces permutations de taille 3: ["aaa", "aab", "aac", "aba", "abb", "abc", "aca", "acb", «acc», «baa», «bab», «bac», «bba», «bbb», «bbc», «bca», «bcb», «bcc», «caa», «cab», «cac» "," cba "," cbb "," cbc "," cca "," ccb "," ccc "]. Ceci est une erreur.
ajouté l'auteur pmc255, source

Vous allez avoir beaucoup de ficelles, c'est sûr ...

\sum_{i=x}^y{\frac{r!}{{(r-i)}!}} http://www.codecogs.com/eq.latex?%5Csum_%7Bi=x%7D%5Ey%20%7B%20%5Cfrac%7Br!%7D%7B%7B(r-i)%7D!%7D%20%7D
Where, x and y is how you define them and r is the number of characters we are selecting from --if I am understanding you correctly. You should definitely generate these as needed and not get sloppy and say, generate a powerset and then filter the length of strings.

Ce qui suit n'est certainement pas la meilleure façon de les générer, mais c'est un côté intéressant, néanmoins.

Knuth (volume 4, fascicule 2, 7.2.1.3) nous dit que (s, t) -combinaison équivaut à s + 1 choses prises à la fois avec répétition - une (s, t) -combinaison est une notation utilisée par Knuth qui est égal à {t \ choose {s + t } http://www.codecogs.com/eq.latex?%7Bt%20%5Cchoose%20%7Bs+t%7D%7D . Nous pouvons comprendre cela en générant d'abord chaque (s, t) -combinaison sous forme binaire (donc, de longueur (s + t)) et en comptant le nombre de 0 à gauche de chaque 1.

10001000011101 --> becomes the permutation: {0, 3, 4, 4, 4, 1}

0
ajouté

Bien que cela ne réponde pas exactement à votre question, voici une façon de générer toutes les permutations des lettres d'un certain nombre de chaînes de même longueur: par exemple, si vos mots étaient "café", "joomla" et "moodle", vous pouvez Attendez-vous à des sorties comme "coodle", "joodee", "joffle", etc.

Fondamentalement, le nombre de combinaisons est le (nombre de mots) à la puissance de (nombre de lettres par mot). Donc, choisissez un nombre aléatoire entre 0 et le nombre de combinaisons - 1, convertissez ce nombre en base (nombre de mots), puis utilisez chaque chiffre de ce nombre comme indicateur pour quel mot prendre la lettre suivante.

Par exemple: dans l'exemple ci-dessus. 3 mots, 6 lettres = 729 combinaisons. Choisissez un nombre aléatoire: 465. Convertissez en base 3: 122020. Prenez la première lettre du mot 1, la 2ème du mot 2, la 3ème du mot 2, la 4ème du mot 0 ... et vous obtenez ... "joofle".

Si vous voulez toutes les permutations, faites simplement une boucle de 0 à 728. Bien sûr, si vous choisissez simplement une valeur aléatoire, une façon beaucoup moins confuse de simplifier serait de faire une boucle sur les lettres. Cette méthode vous permet d'éviter la récursivité, si vous voulez toutes les permutations, et vous donne l'impression que vous connaissez Maths (tm) !

Si le nombre de combinaisons est excessif, vous pouvez le décomposer en une série de mots plus petits et les concaténer à la fin.

0
ajouté

Here is a link that describes how to print permutations of a string. http://nipun-linuxtips.blogspot.in/2012/11/print-all-permutations-of-characters-in.html

0
ajouté

Un peu de code Java basé sur La réponse de Sarp :

public class permute {

    static void permute(int level, String permuted,
                    boolean used[], String original) {
        int length = original.length();
        if (level == length) {
            System.out.println(permuted);
        } else {
            for (int i = 0; i < length; i++) {
                if (!used[i]) {
                    used[i] = true;
                    permute(level + 1, permuted + original.charAt(i),
                       used, original);
                    used[i] = false;
                }
            }
        }
    }

    public static void main(String[] args) {
        String s = "hello";
        boolean used[] = {false, false, false, false, false};
        permute(0, "", used, s);
    }
}
0
ajouté
En tant que commentaire, notez que pour une chaîne avec des caractères répétés, cela ne produira pas les permutations uniques. Cela pourrait être résolu avec un hachage, mais cela pourrait être un problème avec de longues chaînes.
ajouté l'auteur Glenn, source
Vous pouvez utiliser des tableaux char plutôt que des chaînes pour que cela fonctionne plus vite puisque les chaînes sont immuables dans Java.
ajouté l'auteur Abhijeet Kashnia, source
def gen( x,y,list): #to generate all strings inserting y at different positions
list = []
list.append( y+x )
for i in range( len(x) ):
    list.append( func(x,0,i) + y + func(x,i+1,len(x)-1) )
return list 

def func( x,i,j ): #returns x[i..j]
z = '' 
for i in range(i,j+1):
    z = z+x[i]
return z 

def perm( x , length , list ): #perm function
if length == 1 : # base case
    list.append( x[len(x)-1] )
    return list 
else:
    lists = perm( x , length-1 ,list )
    lists_temp = lists #temporarily storing the list 
    lists = []
    for i in range( len(lists_temp) ) :
        list_temp = gen(lists_temp[i],x[length-2],lists)
        lists += list_temp 
    return lists
0
ajouté

En Perl, si vous voulez vous limiter à l'alphabet minuscule, vous pouvez le faire:

my @result = ("a" .. "zzzz");

Cela donne toutes les chaînes possibles entre 1 et 4 caractères en utilisant des caractères minuscules. Pour les majuscules, remplacez "a" par "A" et "zzzz" par "ZZZZ" .

Pour les cas mixtes, cela devient beaucoup plus difficile, et probablement pas faisable avec un des opérateurs internes de Perl comme ça.

0
ajouté

Ruby répond que ça marche:

class String
  def each_char_with_index
    0.upto(size - 1) do |index|
      yield(self[index..index], index)
    end
  end
  def remove_char_at(index)
    return self[1..-1] if index == 0
    self[0..(index-1)] + self[(index+1)..-1]
  end
end

def permute(str, prefix = '')
  if str.size == 0
    puts prefix
    return
  end
  str.each_char_with_index do |char, index|
    permute(str.remove_char_at(index), prefix + char)
  end
end

# example
# permute("abc")
0
ajouté
Pour un one liner de fantaisie dans Ruby: stackoverflow.com/questions/5773961/…
ajouté l'auteur dojosto, source

Voici une version non récursive que j'ai trouvée, en javascript. Ce n'est pas basé sur celui non-récursif de Knuth ci-dessus, bien qu'il ait quelques similarités dans l'échange d'éléments. J'ai vérifié son exactitude pour les tableaux d'entrée de jusqu'à 8 éléments.

Une optimisation rapide serait de pré-voler le tableau out et d'éviter push() .

L'idée de base est:

  1. Étant donné un seul tableau source, générez un premier ensemble de tableaux qui permutent le premier élément avec chaque élément suivant, laissant chaque fois les autres éléments non perturbés. par exemple: donné 1234, générer 1234, 2134, 3214, 4231.

  2. Utilise chaque tableau de la passe précédente comme graine pour un nouveau passage, mais au lieu d'échanger le premier élément, échangez le second élément avec chaque élément suivant. En outre, cette fois, n'incluez pas le tableau d'origine dans la sortie.

  3. Répétez l'étape 2 jusqu'à la fin.

Voici l'exemple de code:

function oxe_perm(src, depth, index)
{
    var perm = src.slice();     // duplicates src.
    perm = perm.split("");
    perm[depth] = src[index];
    perm[index] = src[depth];
    perm = perm.join("");
    return perm;
}

function oxe_permutations(src)
{
    out = new Array();

    out.push(src);

    for (depth = 0; depth < src.length; depth++) {
        var numInPreviousPass = out.length;
        for (var m = 0; m < numInPreviousPass; ++m) {
            for (var n = depth + 1; n < src.length; ++n) {
                out.push(oxe_perm(out[m], depth, n));
            }
        }
    }

    return out;
}
0
ajouté

Il existe une implémentation Java itérative dans UncommonsMaths (fonctionne pour une liste d'objets ):

/**
 * Generate the indices into the elements array for the next permutation. The
 * algorithm is from Kenneth H. Rosen, Discrete Mathematics and its 
 * Applications, 2nd edition (NY: McGraw-Hill, 1991), p. 284)
 */
private void generateNextPermutationIndices()
{
    if (remainingPermutations == 0)
    {
        throw new IllegalStateException("There are no permutations " +
             "remaining. Generator must be reset to continue using.");
    }
    else if (remainingPermutations < totalPermutations)
    {
        // Find largest index j with 
        // permutationIndices[j] < permutationIndices[j + 1]
        int j = permutationIndices.length - 2;
        while (permutationIndices[j] > permutationIndices[j + 1])
        {
            j--;
        }

        // Find index k such that permutationIndices[k] is smallest integer 
        // greater than permutationIndices[j] to the right
        // of permutationIndices[j].
        int k = permutationIndices.length - 1;
        while (permutationIndices[j] > permutationIndices[k])
        {
            k--;
        }

        // Interchange permutation indices.
        int temp = permutationIndices[k];
        permutationIndices[k] = permutationIndices[j];
        permutationIndices[j] = temp;

        // Put tail end of permutation after jth position in increasing order.
        int r = permutationIndices.length - 1;
        int s = j + 1;

        while (r > s)
        {
            temp = permutationIndices[s];
            permutationIndices[s] = permutationIndices[r];
            permutationIndices[r] = temp;
            r--;
            s++;
        }
    }
    --remainingPermutations;
}

/**
 * Generate the next permutation and return a list containing
 * the elements in the appropriate order.  This overloaded method
 * allows the caller to provide a list that will be used and returned.
 * The purpose of this is to improve performance when iterating over
 * permutations.  If the {@link #nextPermutationAsList()} method is
 * used it will create a new list every time.  When iterating over
 * permutations this will result in lots of short-lived objects that
 * have to be garbage collected.  This method allows a single list
 * instance to be reused in such circumstances.
 * @param destination Provides a list to use to create the
 * permutation.  This is the list that will be returned, once
 * it has been filled with the elements in the appropriate order.
 * @return The next permutation as a list.
 */
public List nextPermutationAsList(List destination)
{
    generateNextPermutationIndices();
    // Generate actual permutation.
    destination.clear();
    for (int i : permutationIndices)
    {
        destination.add(elements[i]);
    }
    return destination;
}

Source complète

0
ajouté

Vous pouvez consulter " Énumérer efficacement les sous-ensembles d'un ensemble ", qui décrit un algorithme pour faire partie de ce que vous voulez - générer rapidement tous les sous-ensembles de N caractères de longueur x à y. Il contient une implémentation en C.

Pour chaque sous-ensemble, vous devez toujours générer toutes les permutations. Par exemple si vous vouliez 3 caractères de "abcde", cet algorithme vous donnerait "abc", "abd", "abe" ... mais il faudrait permuter chacun pour obtenir "acb", "bac", "bca", etc.

0
ajouté

Il y a beaucoup de bonnes réponses ici. Je suggère également une solution récursive très simple en C ++.

#include 
#include 

template
void permutations(std::string s, Consume consume, std::size_t start = 0) {
    if (start == s.length()) consume(s);
    for (std::size_t i = start; i < s.length(); i++) {
        std::swap(s[start], s[i]);
        permutations(s, consume, start + 1);
    }
}

int main(void) {
    std::string s = "abcd";
    permutations(s, [](std::string s) {
        std::cout << s << std::endl;
    });
}

Note: strings with repeated characters will not produce unique permutations.

0
ajouté
Cette solution est excellente et mérite plus d'attention.
ajouté l'auteur Mike S, source
def permutation(str)
  posibilities = []
  str.split('').each do |char|
    if posibilities.size == 0
      posibilities[0] = char.downcase
      posibilities[1] = char.upcase
    else
      posibilities_count = posibilities.length
      posibilities = posibilities + posibilities
      posibilities_count.times do |i|
        posibilities[i] += char.downcase
        posibilities[i+posibilities_count] += char.upcase
      end
    end
  end
  posibilities
end

Voici mon point de vue sur une version non récursive

0
ajouté

Solution non récursive selon Knuth, exemple Python:

def nextPermutation(perm):
    k0 = None
    for i in range(len(perm)-1):
        if perm[i]< perm[i]:
            l0 = i

    perm[k0], perm[l0] = perm[l0], perm[k0]
    perm[k0+1:] = reversed(perm[k0+1:])
    return perm

perm=list("12345")
while perm:
    print perm
    perm = nextPermutation(perm)
0
ajouté
Ce qui est intéressant, c'est que nextPermutation() est sans état? il ne prend que l'entrée à permuter et les index ne sont pas maintenus de l'itération à l'itération. Il est capable de le faire en supposant que l'entrée initiale a été triée et de trouver des index ( k0 et l0 ) lui-même, en fonction de l'endroit où la commande est maintenue. Le tri d'une entrée comme "54321" -> "12345" permettrait à cet algorithme de trouver toutes les permutations attendues. Mais comme il fait beaucoup de travail supplémentaire pour retrouver ces index pour chaqu
ajouté l'auteur spaaarky21, source
En fait, cela ne fonctionne pas lorsque la chaîne n'est pas triée. Si vous essayez avec "54321" seule chaîne ONE est montrée (elle-même).
ajouté l'auteur tonjo, source

La solution pythonique:

from itertools import permutations
s = 'ABCDEF'
p = [''.join(x) for x in permutations(s)]
0
ajouté

... et voici la version C:

void permute(const char *s, char *out, int *used, int len, int lev)
{
    if (len == lev) {
        out[lev] = '\0';
        puts(out);
        return;
    }

    int i;
    for (i = 0; i < len; ++i) {
        if (! used[i])
            continue;

        used[i] = 1;
        out[lev] = s[i];
        permute(s, out, used, len, lev + 1);
        used[i] = 0;
    }
    return;
}
0
ajouté

Il y a plusieurs moyens de le faire. Les méthodes communes 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 dans chaque itération, pour toutes les chaînes produites dans la dernière itération, ajoutez cette chaîne concaténée avec chaque caractère de la chaîne individuellement. (l'index de variable dans le code ci-dessous garde trace du début de la dernière et de la prochaine itération)

Un pseudocode:

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 longueur inférieure à x, elles seront les premières entrées (x-1) * len (originalString) de la liste.

0
ajouté
Pourquoi d'abord stocker la liste des éléments, puis l'effacer? (se référant à la ligne 1 et 3 dans le pseudocode).
ajouté l'auteur Håvard Geithus, source
Qu'est-ce que y (ligne 4)?
ajouté l'auteur Jaseem, source
@Jaseem De la question: "toutes les permutations possibles d'une chaîne entre x et y caractères en longueur"
ajouté l'auteur cksubs, source

Je ne sais pas pourquoi vous voudriez faire cela en premier lieu. L'ensemble résultant pour toute valeur modérément grande de x et y sera énorme, et croîtra exponentiellement lorsque x et / ou y grossiront.

Disons que votre ensemble de caractères possibles est les 26 lettres minuscules de l'alphabet, et vous demandez à votre application de générer toutes les permutations où longueur = 5. En supposant que vous ne manquiez pas de mémoire, vous aurez 11 881 376 (soit 26 à la puissance de 5) cordes en arrière. Bump cette longueur jusqu'à 6, et vous aurez 308,915,776 chaînes de retour. Ces chiffres deviennent douloureusement importants, 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). S'amuser.

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);
            }
        }
    }
}
0
ajouté
Longtemps mais ne les générez-vous pas avec répétition?
ajouté l'auteur Kakira, source

Solution récursive en C ++

int main (int argc, char * const argv[]) {
        string s = "sarp";
        bool used [4];
        permute(0, "", used, s);
}

void permute(int level, string permuted, bool used [], string &original) {
    int length = original.length();

    if(level == length) { // permutation complete, display
        cout << permuted << endl;
    } else {
        for(int i=0; i
0
ajouté
@Sarp Centel: ce code fonctionne-t-il en C ++? << code> chaîne </ code >>
ajouté l'auteur Lazer, source

Voici un mot simple solution récursive C #:

Méthode:

public ArrayList CalculateWordPermutations(string[] letters, ArrayList words, int index)
        {
            bool finished = true;
            ArrayList newWords = new ArrayList();
            if (words.Count == 0)
            {
                foreach (string letter in letters)
                {
                    words.Add(letter);
                }
            }

            for(int j=index; j

Appelant:

string[] letters = new string[]{"a","b","c"};
ArrayList words = CalculateWordPermutations(letters, new ArrayList(), 0);
0
ajouté

Voici une solution simple en C #.

Il génère uniquement les permutations distinctes d'une chaîne donnée.

    static public IEnumerable permute(string word)
    {
        if (word.Length > 1)
        {

            char character = word[0];
            foreach (string subPermute in permute(word.Substring(1)))
            {

                for (int index = 0; index <= subPermute.Length; index++)
                {
                    string pre = subPermute.Substring(0, index);
                    string post = subPermute.Substring(index);

                    if (post.Contains(character))
                            continue;                       

                    yield return pre + character + post;
                }

            }
        }
        else
        {
            yield return word;
        }
    }
0
ajouté
import java.util.*;

public class all_subsets {
    public static void main(String[] args) {
        String a = "abcd";
        for(String s: all_perm(a)) {
            System.out.println(s);
        }
    }

    public static Set concat(String c, Set lst) {
        HashSet ret_set = new HashSet();
        for(String s: lst) {
            ret_set.add(c+s);
        }
        return ret_set;
    }

    public static HashSet all_perm(String a) {
        HashSet set = new HashSet();
        if(a.length() == 1) {
            set.add(a);
        } else {
            for(int i=0; i
0
ajouté
Version non récursive: stackoverflow.com/a/28527943/1266326
ajouté l'auteur MLProgrammer-CiM, source

permute (ABC) -> A.perm(BC) -> A.perm[B.perm(C)] -> A.perm[(*BC), (CB*)] -> [(*ABC), (BAC), (BCA*), (*ACB), (CAB), (CBA*)] To remove duplicates when inserting each alphabet check to see if previous string ends with the same alphabet (why? -exercise)

public static void main(String[] args) {

    for (String str : permStr("ABBB")){
        System.out.println(str);
    }
}

static Vector permStr(String str){

    if (str.length() == 1){
        Vector ret = new Vector();
        ret.add(str);
        return ret;
    }

    char start = str.charAt(0);
    Vector endStrs = permStr(str.substring(1));
    Vector newEndStrs = new Vector();
    for (String endStr : endStrs){
        for (int j = 0; j <= endStr.length(); j++){
            if (endStr.substring(0, j).endsWith(String.valueOf(start)))
                break;
            newEndStrs.add(endStr.substring(0, j) + String.valueOf(start) + endStr.substring(j));
        }
    }
    return newEndStrs;
}

Imprime toutes les permutations sans doublons

0
ajouté

Ce code en python, lorsqu'il est appelé avec allowed_characters défini sur [0,1] et 4 caractères max, générerait 2 ^ 4 résultats:

['0000', '0001', '0010', '0011', '0100', '0101', '0110', '0111', '1000', '1001', '1010', '1011 ',' 1100 ',' 1101 ',' 1110 ',' 1111 ']

def generate_permutations(chars = 4) :

#modify if in need!
    allowed_chars = [
        '0',
        '1',
    ]

    status = []
    for tmp in range(chars) :
        status.append(0)

    last_char = len(allowed_chars)

    rows = []
    for x in xrange(last_char ** chars) :
        rows.append("")
        for y in range(chars - 1 , -1, -1) :
            key = status[y]
            rows[x] = allowed_chars[key] + rows[x]

        for pos in range(chars - 1, -1, -1) :
            if(status[pos] == last_char - 1) :
                status[pos] = 0
            else :
                status[pos] += 1
                break;

    return rows

import sys


print generate_permutations()

J'espère que cela vous est utile. Fonctionne avec n'importe quel personnage, pas seulement des chiffres

0
ajouté
Ce ne sont pas des permutations mais une sélection de sous-ensemble, c'est-à-dire ABC & 001 = C alors qu'une permutation valide doit avoir les trois caractères.
ajouté l'auteur Schultz9999, source
euh? désolé, je ne comprends pas ce que vous dites. Si vous le corrigez, laissez une version corrigée, je ferai la communauté wiki
ajouté l'auteur droope, source

J'en avais besoin aujourd'hui, et bien que les réponses déjà données m'indiquaient dans la bonne direction, elles n'étaient pas tout à fait ce que je voulais.

Voici une implémentation utilisant la méthode de Heap. La longueur du tableau doit être d'au moins 3 et, pour des raisons pratiques, ne pas être supérieure à 10 ou plus, en fonction de ce que vous voulez faire, de la patience et de la vitesse d'horloge.

Avant d'entrer votre boucle, initialisez Perm (1 à N) avec la première permutation, Stack (3 à N) avec des zéros *, et Level avec 2 **. À la fin de la boucle, appelez NextPerm , ce qui retournera false lorsque nous aurons terminé.

* VB le fera pour vous.

** Vous pouvez changer NextPerm un peu pour rendre cela inutile, mais c'est plus clair comme ça.

Option Explicit

Function NextPerm(Perm() As Long, Stack() As Long, Level As Long) As Boolean
Dim N As Long
If Level = 2 Then
    Swap Perm(1), Perm(2)
    Level = 3
Else
    While Stack(Level) = Level - 1
        Stack(Level) = 0
        If Level = UBound(Stack) Then Exit Function
        Level = Level + 1
    Wend
    Stack(Level) = Stack(Level) + 1
    If Level And 1 Then N = 1 Else N = Stack(Level)
    Swap Perm(N), Perm(Level)
    Level = 2
End If
NextPerm = True
End Function

Sub Swap(A As Long, B As Long)
A = A Xor B
B = A Xor B
A = A Xor B
End Sub

'This is just for testing.
Private Sub Form_Paint()
Const Max = 8
Dim A(1 To Max) As Long, I As Long
Dim S(3 To Max) As Long, J As Long
Dim Test As New Collection, T As String
For I = 1 To UBound(A)
    A(I) = I
Next
Cls
ScaleLeft = 0
J = 2
Do
    If CurrentY + TextHeight("0") > ScaleHeight Then
        ScaleLeft = ScaleLeft - TextWidth(" 0 ") * (UBound(A) + 1)
        CurrentY = 0
        CurrentX = 0
    End If
    T = vbNullString
    For I = 1 To UBound(A)
        Print A(I);
        T = T & Hex(A(I))
    Next
    Print
    Test.Add Null, T
Loop While NextPerm(A, S, J)
J = 1
For I = 2 To UBound(A)
    J = J * I
Next
If J <> Test.Count Then Stop
End Sub

D'autres méthodes sont décrites par divers auteurs. Knuth en décrit deux, l'un donne l'ordre lexical, mais est complexe et lent, l'autre est connu comme la méthode des changements simples. Jie Gao et Dianjun Wang ont également écrit un article intéressant.

0
ajouté

Il est préférable d'utiliser backtracking

#include 
#include 

void swap(char *a, char *b) {
    char temp;
    temp = *a;
    *a = *b;
    *b = temp;
}

void print(char *a, int i, int n) {
    int j;
    if(i == n) {
        printf("%s\n", a);
    } else {
        for(j = i; j <= n; j++) {
            swap(a + i, a + j);
            print(a, i + 1, n);
            swap(a + i, a + j);
        }
    }
}

int main(void) {
    char a[100];
    gets(a);
    print(a, 0, strlen(a) - 1);
    return 0;
}
0
ajouté
Meilleure solution everrrrrrrrr
ajouté l'auteur GrowinMan, source
C'est un peu lisible et facile à saisir juste sur un coup d'oeil.
ajouté l'auteur joey rohan, source

c # itératif:

public List Permutations(char[] chars)
    {
        List words = new List();
        words.Add(chars[0].ToString());
        for (int i = 1; i < chars.Length; ++i)
        {
            int currLen = words.Count;
            for (int j = 0; j < currLen; ++j)
            {
                var w = words[j];
                for (int k = 0; k <= w.Length; ++k)
                {
                    var nstr = w.Insert(k, chars[i].ToString());
                    if (k == 0)
                        words[j] = nstr;
                    else
                        words.Add(nstr);
                }
            }
        }
        return words;
    }
0
ajouté

La récursivité Java suivante imprime toutes les permutations d'une chaîne donnée:

//call it as permut("",str);

public void permut(String str1,String str2){
    if(str2.length() != 0){
        char ch = str2.charAt(0);
        for(int i = 0; i <= str1.length();i++)
            permut(str1.substring(0,i) + ch + str1.substring(i,str1.length()),
                     str2.substring(1,str2.length()));
    }else{
    System.out.println(str1);
    }
}

Voici la version mise à jour de la méthode "permut" ci-dessus qui fait n! (n factoriel) appels moins récursifs par rapport à la méthode ci-dessus

//call it as permut("",str);

public void permut(String str1,String str2){
   if(str2.length() > 1){
       char ch = str2.charAt(0);
       for(int i = 0; i <= str1.length();i++)
          permut(str1.substring(0,i) + ch + str1.substring(i,str1.length()),
                 str2.substring(1,str2.length()));
   }else{
    char ch = str2.charAt(0);
    for(int i = 0; i <= str1.length();i++)
        System.out.println(str1.substring(0,i) + ch +    str1.substring(i,str1.length()),
                 str2.substring(1,str2.length()));
   }
}
0
ajouté
@TaoZhang merci pour le complément, je ne l'ai pas copié de n'importe où mais il est possible que quelqu'un ait créé un algo similaire. De toute façon, j'ai mis à jour le code ci-dessus pour les appels moins récursifs
ajouté l'auteur Ramy, source
C'est la solution la plus propre, et je crois que je l'ai déjà vu dans le livre "Cracking the Coding Interview"
ajouté l'auteur Tao Zhang, source

Une solution récursive en python. La bonne chose à propos de ce code est qu'il exporte un dictionnaire, avec des clés en tant que chaînes et toutes les permutations possibles en tant que valeurs. Toutes les longueurs de chaînes possibles sont incluses, donc en fait, vous créez un surensemble.

Si vous n'avez besoin que des permutations finales, vous pouvez supprimer d'autres clés du dictionnaire.

Dans ce code, le dictionnaire des permutations est global.

Dans le cas de base, je stocke la valeur comme les deux possibilités dans une liste. perms ['ab'] = ['ab', 'ba'] .

Pour des longueurs de corde plus élevées, la fonction fait référence à des longueurs de corde plus basses et incorpore les permutations calculées précédemment.

La fonction fait deux choses:

  • s'appelle lui-même avec une chaîne plus petite
  • renvoie une liste de permutations d'une chaîne particulière si elle est déjà disponible. Si retourné à lui-même, ceux-ci seront utilisés pour ajouter au caractère et créer de nouvelles permutations.

Cher pour la mémoire.

perms = {}
def perm(input_string):
    global perms
    if input_string in perms:
        return perms[input_string] # This will send a list of all permutations
    elif len(input_string) == 2:
        perms[input_string] = [input_string, input_string[-1] + input_string [-2]]
        return perms[input_string]
    else:
        perms[input_string] = []
        for index in range(0, len(input_string)):
            new_string = input_string[0:index] + input_string[index +1:]
            perm(new_string)
            for entries in perms[new_string]:
                perms[input_string].append(input_string[index] + entries)
    return perms[input_string]
0
ajouté

Solution récursive avec la méthode main() du pilote.

public class AllPermutationsOfString {
public static void stringPermutations(String newstring, String remaining) {
    if(remaining.length()==0)
        System.out.println(newstring);

    for(int i=0; i

}

0
ajouté

Eh bien, voici une solution O (n!) Élégante et non-récursive:

public static StringBuilder[] permutations(String s) {
        if (s.length() == 0)
            return null;
        int length = fact(s.length());
        StringBuilder[] sb = new StringBuilder[length];
        for (int i = 0; i < length; i++) {
            sb[i] = new StringBuilder();
        }
        for (int i = 0; i < s.length(); i++) {
            char ch = s.charAt(i);
            int times = length / (i + 1);
            for (int j = 0; j < times; j++) {
                for (int k = 0; k < length / times; k++) {
                    sb[j * length / times + k].insert(k, ch);
                }
            }
        }
        return sb;
    }
0
ajouté

code écrit pour la langue java:

package namo.algorithms;

import java.util.Scanner;

Permuations de classe publique {

public static int totalPermutationsCount = 0;
    public static void main(String[] args) {

        Scanner sc = new Scanner(System.in);
        System.out.println("input string : ");
        String inputString = sc.nextLine();
        System.out.println("given input String ==> "+inputString+ " :: length is = "+inputString.length());
        findPermuationsOfString(-1, inputString);
        System.out.println("**************************************");
        System.out.println("total permutation strings ==> "+totalPermutationsCount);
    }


    public  static void findPermuationsOfString(int fixedIndex, String inputString) {
        int currentIndex = fixedIndex +1;

        for (int i = currentIndex; i < inputString.length(); i++) {
            //swap elements and call the findPermuationsOfString()

            char[] carr = inputString.toCharArray();
            char tmp = carr[currentIndex];
            carr[currentIndex] = carr[i];
            carr[i] = tmp;
            inputString =  new String(carr);

            //System.out.println("chat At : current String ==> "+inputString.charAt(currentIndex));
            if(currentIndex == inputString.length()-1) {
                totalPermutationsCount++;
                System.out.println("permuation string ==> "+inputString);
            } else {
                //System.out.println("in else block>>>>");
                findPermuationsOfString(currentIndex, inputString);
                 char[] rarr = inputString.toCharArray();
                    char rtmp = carr[i];
                    carr[i] = carr[currentIndex];
                    carr[currentIndex] = rtmp;
                    inputString =  new String(carr);
            }
        }
    }

}

0
ajouté

Les permutations de chaînes possibles peuvent être calculées en utilisant la fonction récursive. Voici une des solutions possibles.

public static String insertCharAt(String s, int index, char c) {
        StringBuffer sb = new StringBuffer(s);
        StringBuffer sbb = sb.insert(index, c);
        return sbb.toString();
}

public static ArrayList getPerm(String s, int index) {
        ArrayList perm = new ArrayList();

        if (index == s.length()-1) {
            perm.add(String.valueOf(s.charAt(index)));
            return perm;
        }

        ArrayList p = getPerm(s, index+1);
        char c = s.charAt(index);

        for(String pp : p) {
            for (int idx=0; idx perm = getPerm(s,0);
        System.out.println(s+" --> total permutation are :: "+perm.size());
        System.out.println(perm.toString());
}
0
ajouté