Genera una lista de todas las permutaciones posibles de una cadena

Respuestas:

70

Hay varias formas de hacer esto. Los métodos comunes usan recursividad, memorización o programación dinámica. La idea básica es que produzca una lista de todas las cadenas de longitud 1, luego, en cada iteración, para todas las cadenas producidas en la última iteración, agregue esa cadena concatenada con cada carácter en la cadena individualmente. (el índice variable en el código a continuación realiza un seguimiento del inicio de la última y la próxima iteración)

Algunos pseudocódigo:

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)

entonces deberá eliminar todas las cadenas de menos de x de longitud, serán las primeras entradas (x-1) * len (originalString) en la lista.

alumb
fuente
44
¿Por qué almacenar primero la lista de elementos y luego borrarla? (refiriéndose a las líneas 1 y 3 en el pseudocódigo).
Håvard Geithus
66
¿Qué es y (línea 4)?
Jaseem
77
@Jaseem De la pregunta: "todas las permutaciones posibles de una cadena entre caracteres x e y de longitud"
ck_
39

Es mejor usar retroceder

#include <stdio.h>
#include <string.h>

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;
}
Unnykrishnan S
fuente
3
La mejor solución: everrrrrrrrr
GrowinMan
25

Tendrás muchas cuerdas, eso seguro ...

\ sum_ {i = x} ^ y {\ frac {r!} {{(ri)}!}}
Donde x e y es cómo los define yr es el número de caracteres que estamos seleccionando, si lo entiendo correctamente. Definitivamente, debe generarlos según sea necesario y no ponerse descuidado y decir, generar un conjunto de potencia y luego filtrar la longitud de las cadenas.

Lo siguiente definitivamente no es la mejor manera de generarlos, pero es interesante, no obstante.

Knuth (volumen 4, fascículo 2, 7.2.1.3) nos dice que (s, t) combinación es equivalente a s + 1 cosas tomadas t a la vez con repetición - una combinación (s, t) es notación utilizada por Knuth que es igual a {t \ elegir {s + t}. Podemos resolver esto generando primero cada combinación (s, t) en forma binaria (entonces, de longitud (s + t)) y contando el número de 0 a la izquierda de cada 1.

10001000011101 -> se convierte en la permutación: {0, 3, 4, 4, 4, 1}

nlucaroni
fuente
15

Solución no recursiva según Knuth, ejemplo de Python:

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

    l0 = k0+1
    for i in range(k0+1, len(perm)):
        if perm[k0] < 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)
Rockportrocker
fuente
2
En realidad, esto no funciona cuando la cadena no está ordenada. Si intenta con "54321"solo se muestra UNA cadena (en sí).
tonjo
1
Lo interesante es que no nextPermutation()tiene estado: solo se necesita la entrada para permutar y los índices no se mantienen de iteración a iteración. Puede hacerlo asumiendo que la entrada inicial se ordenó y encontrando índices ( k0y l0) en sí mismos, en función del lugar donde se mantiene el orden. Ordenar una entrada como "54321" -> "12345" permitiría a este algoritmo encontrar todas las permutaciones esperadas. Pero dado que hace una buena cantidad de trabajo extra para reencontrar esos índices para cada permutación que genera, existen formas más eficientes de hacerlo de manera no recursiva.
spaaarky21
13

Puede mirar " Enumerar eficientemente los subconjuntos de un conjunto ", que describe un algoritmo para hacer parte de lo que desea: generar rápidamente todos los subconjuntos de N caracteres de longitud x a y. Contiene una implementación en C.

Para cada subconjunto, aún tendría que generar todas las permutaciones. Por ejemplo, si quisieras 3 caracteres de "abcde", este algoritmo te daría "abc", "abd", "abe" ... pero tendrías que permutar cada uno para obtener "acb", "bac", "bca", etc.

AShelly
fuente
13

Algunos códigos Java que funcionan basados ​​en la respuesta 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);
    }
}
Lazer
fuente
Como comentario, tenga en cuenta que para una cadena con caracteres repetidos esto no producirá las permutaciones únicas. Esto podría resolverse con un hash, pero podría ser un problema con cadenas largas.
Glenn
8
Es posible que desee utilizar matrices de caracteres en lugar de cadenas para que esto se ejecute más rápido, ya que las cadenas son inmutables en Java.
Abhijeet Kashnia 01 de
13

Aquí hay una solución simple en C #.

Genera solo las permutaciones distintas de una cadena dada.

    static public IEnumerable<string> 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;
        }
    }
Prakhar Gupta
fuente
12

Hay muchas buenas respuestas aquí. También sugiero una solución recursiva muy simple en C ++.

#include <string>
#include <iostream>

template<typename Consume>
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;
    });
}

Nota : las cadenas con caracteres repetidos no producirán permutaciones únicas.

gd1
fuente
9

Acabo de preparar esto rápidamente en 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

Puede buscar en la API de lenguaje las funciones integradas de tipo de permutación, y puede escribir código más optimizado, pero si los números son tan altos, no estoy seguro de que haya una gran forma de obtener muchos resultados .

De todos modos, la idea detrás del código es comenzar con una cadena de longitud 0, luego realizar un seguimiento de todas las cadenas de longitud Z donde Z es el tamaño actual en la iteración. Luego, revisa cada cadena y agrega cada carácter a cada cadena. Finalmente, al final, elimine los que estaban por debajo del umbral x y devuelva el resultado.

No lo probé con entradas potencialmente sin sentido (lista de caracteres nulos, valores extraños de x e y, etc.).

Mike Stone
fuente
11
Este código es incorrecto. Generará permutaciones no válidas, como las que tienen caracteres repetidos. Por ejemplo, para la cadena "abc", genera estas permutaciones de tamaño 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 "]. Esto es incorrecto.
pmc255
8

Esta es una traducción de la versión Ruby de Mike, a 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)))))

Y otra versión, un poco más corta y con más funciones de bucle:

(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)))))
Martín
fuente
8

Aquí hay una palabra simple C # solución recursiva:

Método:

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<words.Count; j++)
            {
                string word = (string)words[j];
                for(int i =0; i<letters.Length; i++)
                {
                    if(!word.Contains(letters[i]))
                    {
                        finished = false;
                        string newWord = (string)word.Clone();
                        newWord += letters[i];
                        newWords.Add(newWord);
                    }
                }
            }

            foreach (string newWord in newWords)
            {   
                words.Add(newWord);
            }

            if(finished  == false)
            {
                CalculateWordPermutations(letters, words, words.Count - newWords.Count);
            }
            return words;
        }

Vocación:

string[] letters = new string[]{"a","b","c"};
ArrayList words = CalculateWordPermutations(letters, new ArrayList(), 0);
Campeón
fuente
8

... y aquí está la versión 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;
}
Peyman
fuente
8

permute (ABC) -> A.perm (BC) -> A.perm [B.perm (C)] -> A.perm [( * B C), (C B * )] -> [( * A BC ), (B A C), (BC A * ), ( * A CB), (C A B), (CB A * )] Para eliminar duplicados al insertar cada alfabeto, verifique si la cadena anterior termina con el mismo alfabeto (¿por qué? -ejercicio)

public static void main(String[] args) {

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

static Vector<String> permStr(String str){

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

    char start = str.charAt(0);
    Vector<String> endStrs = permStr(str.substring(1));
    Vector<String> newEndStrs = new Vector<String>();
    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 todas las permutaciones sin duplicados

raj
fuente
8

Solución recursiva 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<length; i++) { // try to add an unused character
            if(!used[i]) {
                used[i] = true;
                permute(level+1, original[i] + permuted, used, original); // find the permutations starting with this string
                used[i] = false;
            }
        }
}
Sarp Centel
fuente
7

En Perl, si desea restringirse al alfabeto en minúsculas, puede hacer esto:

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

Esto proporciona todas las cadenas posibles entre 1 y 4 caracteres usando caracteres en minúscula. Para mayúscula, el cambio "a"a "A"y "zzzz"a"ZZZZ" .

Para el caso mixto, se vuelve mucho más difícil y probablemente no sea factible con uno de los operadores integrados de Perl como ese.

Chris Lutz
fuente
7

Respuesta de Ruby que funciona:

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")
Kem Mason
fuente
Para un trazador de líneas elegante en Ruby: stackoverflow.com/questions/5773961/…
dojosto
6
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<String> concat(String c, Set<String> lst) {
        HashSet<String> ret_set = new HashSet<String>();
        for(String s: lst) {
            ret_set.add(c+s);
        }
        return ret_set;
    }

    public static HashSet<String> all_perm(String a) {
        HashSet<String> set = new HashSet<String>();
        if(a.length() == 1) {
            set.add(a);
        } else {
            for(int i=0; i<a.length(); i++) {
                set.addAll(concat(a.charAt(i)+"", all_perm(a.substring(0, i)+a.substring(i+1, a.length()))));
            }
        }
        return set;
    }
}
Swapneel Patil
fuente
6

La siguiente recursividad de Java imprime todas las permutaciones de una cadena dada:

//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);
    }
}

La siguiente es la versión actualizada del método "permut" anterior que hace que n! (n factorial) llamadas menos recursivas en comparación con el método anterior

//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()));
   }
}
Ramy
fuente
Esta es la solución más limpia, y creo que la he visto antes en el libro "Cracking the Coding Interview"
Tao Zhang
1
@TaoZhang gracias por el complemento, no lo copié de ninguna parte, sin embargo, es posible que alguien haya creado algo similar. De todos modos, he actualizado el código anterior para llamadas menos recursivas
Ramy
5

No estoy seguro de por qué querrías hacer esto en primer lugar. El conjunto resultante para cualquier valor moderadamente grande de x e y será enorme, y crecerá exponencialmente a medida que x y / o crezcan.

Digamos que su conjunto de caracteres posibles son las 26 letras minúsculas del alfabeto, y le pide a su aplicación que genere todas las permutaciones donde longitud = 5. Suponiendo que no se quede sin memoria obtendrá 11,881,376 (es decir, 26 a la potencia de 5) cuerdas hacia atrás. Aumente esa longitud hasta 6 y obtendrá 308,915,776 cadenas de regreso. Estos números se vuelven dolorosamente grandes, muy rápidamente.

Aquí hay una solución que armé en Java. Deberá proporcionar dos argumentos de tiempo de ejecución (correspondientes a x e y). Que te diviertas.

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);
            }
        }
    }
}
Brian Willis
fuente
Mucho tiempo, pero ¿no los estás generando con repetición?
Kakira
5

Aquí hay una versión no recursiva que se me ocurrió, en JavaScript. No se basa en el anterior no recursivo de Knuth, aunque tiene algunas similitudes en el intercambio de elementos. He verificado su corrección para matrices de entrada de hasta 8 elementos.

Una optimización rápida sería realizar un vuelo previo de la outmatriz y evitarpush() .

La idea básica es:

  1. Dada una matriz fuente única, genera un primer conjunto nuevo de matrices que intercambian el primer elemento con cada elemento subsiguiente a su vez, dejando cada uno de los demás elementos sin perturbar. por ejemplo: dado 1234, generar 1234, 2134, 3214, 4231.

  2. Use cada matriz del pase anterior como la semilla para un nuevo pase, pero en lugar de intercambiar el primer elemento, intercambie el segundo elemento con cada elemento posterior. Además, esta vez, no incluya la matriz original en la salida.

  3. Repita el paso 2 hasta que esté listo.

Aquí está el ejemplo de código:

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;
}
orion elenzil
fuente
3

En rubí:

str = "a"
100_000_000.times {puts str.next!}

Es bastante rápido, pero llevará un tiempo =). Por supuesto, puede comenzar en "aaaaaaaa" si las cadenas cortas no son interesantes para usted.

Sin embargo, podría haber malinterpretado la pregunta real: en una de las publicaciones parecía que solo necesitaba una biblioteca de cadenas de fuerza bruta, pero en la pregunta principal parece que necesita permutar una cadena en particular.

Su problema es algo similar a este: http://beust.com/weblog/archives/000491.html (enumere todos los enteros en los que ninguno de los dígitos se repita, lo que resultó en una gran cantidad de idiomas que lo resolvieron, con el ocaml guy usando permutaciones, y algún java guy usando otra solución).

bOR_
fuente
Un problema con su propuesta es que str.next! no iterará sobre todos los caracteres imprimibles. Su ejemplo solo generará letras minúsculas, sin signos de puntuación ni mayúsculas.
Jarsen
3

Necesitaba esto hoy, y aunque las respuestas ya dadas me indicaron en la dirección correcta, no eran exactamente lo que quería.

Aquí hay una implementación usando el método de Heap. La longitud de la matriz debe ser de al menos 3 y, por consideraciones prácticas, no debe ser mayor de 10, dependiendo de lo que desee hacer, paciencia y velocidad de reloj.

Antes de ingresar a su ciclo, inicie Perm(1 To N)con la primera permutación, Stack(3 To N)con ceros * y Levelcon 2**. Al final de la llamada de bucle NextPerm, que devolverá falso cuando hayamos terminado.

* VB lo hará por ti.

** Puedes cambiar NextPerm un poco para que esto sea innecesario, pero es más claro de esta manera.

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

Otros métodos son descritos por varios autores. Knuth describe dos, uno da orden léxico, pero es complejo y lento, el otro se conoce como el método de los cambios simples. Jie Gao y Dianjun Wang también escribieron un artículo interesante.

Cobarde anónimo
fuente
2

Este código en python, cuando se llama con allowed_charactersset to [0,1]y 4 character max, generaría 2 ^ 4 resultados:

['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()

Espero que esto te sea útil. Funciona con cualquier carácter, no solo números

Aminah Nuraini
fuente
No se trata de permutaciones, sino de selección de subconjuntos, es decir, ABC y 001 = C, mientras que una permutación válida debe tener los tres caracteres.
Schultz9999
eh? lo siento, no entiendo lo que dices. Si lo arreglas, deja una versión fija, voy a hacer un wiki en la comunidad
droope
0

Aunque esto no responde a su pregunta exactamente, aquí hay una forma de generar cada permutación de las letras de varias cadenas de la misma longitud: por ejemplo, si sus palabras fueran "café", "joomla" y "moodle", puede esperar resultados como "coodle", "joodee", "joffle", etc.

Básicamente, el número de combinaciones es el (número de palabras) al poder de (número de letras por palabra). Por lo tanto, elija un número aleatorio entre 0 y el número de combinaciones: 1, convierta ese número en base (número de palabras), luego use cada dígito de ese número como el indicador de qué palabra tomar la siguiente letra.

Por ejemplo: en el ejemplo anterior. 3 palabras, 6 letras = 729 combinaciones. Elija un número aleatorio: 465. Convierta a base 3: 122020. Tome la primera letra de la palabra 1, la segunda de la palabra 2, la tercera de la palabra 2, la cuarta de la palabra 0 ... y obtendrá ... "joofle".

Si desea todas las permutaciones, simplemente repita de 0 a 728. Por supuesto, si solo elige un valor aleatorio, una forma mucho más simple y menos confusa sería recorrer las letras. Este método le permite evitar la recursividad, si desea todas las permutaciones, ¡además le hace parecer que conoce Maths (tm) !

Si el número de combinaciones es excesivo, puede dividirlo en una serie de palabras más pequeñas y concatenarlas al final.

nickf
fuente
0

c # iterativo:

public List<string> Permutations(char[] chars)
    {
        List<string> words = new List<string>();
        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;
    }
wliao
fuente
0
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
abkds
fuente
0
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

Aquí está mi opinión sobre una versión no recursiva

Coronilla
fuente
0

La solución pitónica:

from itertools import permutations
s = 'ABCDEF'
p = [''.join(x) for x in permutations(s)]
Abdul Fatir
fuente
0

Bueno, aquí hay una solución elegante, no recursiva, O (n!):

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;
    }
Adilli Adil
fuente