Como eu geraria uma lista de todas as permutações possíveis de uma string com caracteres x e y de comprimento, contendo uma lista variável de caracteres.
Qualquer idioma funcionaria, mas deveria ser portátil.
string
language-agnostic
cross-platform
UnkwnTech
fonte
fonte
Respostas:
Existem várias maneiras de fazer isso. Métodos comuns usam recursão, memorização ou programação dinâmica. A idéia básica é que você produza uma lista de todas as cadeias de comprimento 1 e, em cada iteração, para todas as cadeias produzidas na última iteração, adicione essa cadeia concatenada com cada caractere na cadeia individualmente. (o índice da variável no código abaixo controla o início da última e da próxima iteração)
Algum pseudocódigo:
você precisará remover todas as strings com menos de x de comprimento, elas serão as primeiras (x-1) * len (originalString) da lista.
fonte
É melhor usar o retorno
fonte
Você vai ter muitas cordas, com certeza ...
Onde x e y são como você os define e r é o número de caracteres que estamos selecionando - se estou entendendo corretamente. Você definitivamente deve gerá-las conforme necessário e não ficar desleixado e dizer, gerar um conjunto de energia e depois filtrar o comprimento das seqüências.
Definitivamente, a seguir não é a melhor maneira de gerá-las, mas é um aparte interessante, no entanto.
Knuth (volume 4, fascículo 2, 7.2.1.3) nos diz que a combinação (s, t) é equivalente a s + 1 coisas tomadas t por vez com repetição - uma combinação (s, t) é a notação usada por Knuth que é igual a . Podemos descobrir isso gerando primeiro cada combinação (s, t) em forma binária (portanto, de comprimento (s + t)) e contando o número de 0 à esquerda de cada 1.
10001000011101 -> torna-se a permutação: {0, 3, 4, 4, 4, 1}
fonte
Solução não recursiva de acordo com Knuth, exemplo em Python:
fonte
"54321"
apenas UMA string, será mostrada (ela mesma).nextPermutation()
é sem estado - é necessário apenas a entrada para permutar e os índices não são mantidos de iteração para iteração. É possível fazer isso assumindo que a entrada inicial foi classificada e localizando os índices (k0
el0
) em si, com base em onde a ordem é mantida. Classificar uma entrada como "54321" -> "12345" permitiria que esse algoritmo encontrasse todas as permutações esperadas. Mas, como ele faz uma boa quantidade de trabalho extra para reencontrar esses índices para cada permutação que gera, existem maneiras mais eficientes de fazer isso de forma não recursiva.Você pode consultar " Enumerando eficientemente os subconjuntos de um conjunto ", que descreve um algoritmo para fazer parte do que você deseja - gere rapidamente todos os subconjuntos de caracteres N do comprimento x até y. Ele contém uma implementação em C.
Para cada subconjunto, você ainda precisará gerar todas as permutações. Por exemplo, se você quiser três caracteres de "abcde", esse algoritmo fornecerá "abc", "abd", "abe" ... mas você precisará permutar cada um para obter "acb", "bac", "bca" etc.
fonte
Alguns códigos Java funcionais baseados na resposta de Sarp :
fonte
Aqui está uma solução simples em C #.
Ele gera apenas as permutações distintas de uma determinada string.
fonte
Há muitas boas respostas aqui. Sugiro também uma solução recursiva muito simples em C ++.
Nota : strings com caracteres repetidos não produzirão permutações exclusivas.
fonte
Acabei de preparar isso rapidamente no Ruby:
Você pode procurar na API da linguagem funções do tipo permutação incorporadas e conseguir escrever um código mais otimizado, mas se os números forem altos demais, não tenho certeza de que haja muitos meios de obter muitos resultados .
De qualquer forma, a idéia por trás do código é iniciada com a sequência de comprimento 0 e, em seguida, acompanhe todas as sequências de comprimento Z, em que Z é o tamanho atual da iteração. Em seguida, passe por cada sequência e acrescente cada caractere a cada sequência. Finalmente, no final, remova qualquer um que estivesse abaixo do limite x e retorne o resultado.
Não testei com entrada potencialmente sem sentido (lista de caracteres nulos, valores estranhos de x e y, etc.).
fonte
Esta é uma tradução da versão Ruby de Mike, para o Common Lisp:
E outra versão, um pouco mais curta e com mais recursos de loop:
fonte
Aqui está uma solução recursiva simples da palavra C #:
Método:
A ligar:
fonte
... e aqui está a versão C:
fonte
Imprime todas as permutações sem duplicatas
fonte
Solução recursiva em C ++
fonte
No Perl, se você quiser se restringir ao alfabeto em minúsculas, faça o seguinte:
Isso fornece todas as seqüências possíveis entre 1 e 4 caracteres usando caracteres minúsculos. Para maiúsculas, altere
"a"
para"A"
e"zzzz"
para"ZZZZ"
.Para casos mistos, fica muito mais difícil e provavelmente não é possível com um dos operadores internos do Perl assim.
fonte
Resposta em Ruby que funciona:
fonte
fonte
A seguinte recursão Java imprime todas as permutações de uma determinada sequência:
A seguir está a versão atualizada do método "permut" acima, que torna n! (n fatorial) chamadas menos recursivas em comparação com o método acima
fonte
Não sei por que você desejaria fazer isso em primeiro lugar. O conjunto resultante para quaisquer valores moderadamente grandes de x e y será enorme e aumentará exponencialmente à medida que x e / ou y ficarem maiores.
Digamos que seu conjunto de caracteres possíveis seja as 26 letras minúsculas do alfabeto, e você solicita que seu aplicativo gere todas as permutações em que length = 5. Supondo que você não fique sem memória, obterá 11.881.376 (ou seja, 26 ao poder de 5) cordas de volta. Aumente esse comprimento até 6 e você receberá 308.915.776 strings de volta. Esses números aumentam dolorosamente, muito rapidamente.
Aqui está uma solução que montei em Java. Você precisará fornecer dois argumentos de tempo de execução (correspondentes a x e y). Diverta-se.
fonte
Aqui está uma versão não recursiva que eu criei, em javascript. Não é baseado no não recursivo de Knuth acima, embora tenha algumas semelhanças na troca de elementos. Eu verifiquei sua correção para matrizes de entrada de até 8 elementos.
Uma otimização rápida seria pré-veicular a
out
matriz e evitarpush()
.A ideia básica é:
Dada uma única matriz de origem, gere um primeiro novo conjunto de matrizes que troquem o primeiro elemento com cada elemento subsequente, deixando sempre os outros elementos imperturbáveis. por exemplo: dado 1234, gere 1234, 2134, 3214, 4231.
Use cada matriz da passagem anterior como a semente de uma nova passagem, mas em vez de trocar o primeiro elemento, troque o segundo elemento por cada elemento subsequente. Além disso, desta vez, não inclua a matriz original na saída.
Repita a etapa 2 até concluir.
Aqui está o exemplo de código:
fonte
Em rubi:
É bem rápido, mas vai demorar algum tempo =). Claro, você pode começar em "aaaaaaaa" se as seqüências curtas não forem interessantes para você.
Talvez eu tenha interpretado mal a pergunta real - em uma das postagens, parecia que você só precisava de uma biblioteca de strings da força bruta, mas na pergunta principal parece que você precisa permutar uma determinada string.
Seu problema é um pouco semelhante a este: http://beust.com/weblog/archives/000491.html (liste todos os números inteiros nos quais nenhum dos dígitos se repete, o que resultou em vários idiomas resolvendo-o, com o cara do ocaml usando permutações e cara do java usando outra solução).
fonte
Eu precisava disso hoje e, embora as respostas já dadas me apontassem na direção certa, elas não eram exatamente o que eu queria.
Aqui está uma implementação usando o método Heap. O comprimento da matriz deve ser pelo menos 3 e, por considerações práticas, não deve ser maior que 10 ou mais, dependendo do que você deseja fazer, paciência e velocidade do relógio.
Antes de inserir seu loop, inicialize
Perm(1 To N)
com a primeira permutação,Stack(3 To N)
com zeros * eLevel
com2
**. No final da chamada de loopNextPerm
, que retornará falso quando terminarmos.* VB fará isso por você.
** Você pode alterar um pouco o NextPerm para tornar isso desnecessário, mas fica mais claro assim.
Outros métodos são descritos por vários autores. Knuth descreve dois, um dá ordem lexical, mas é complexo e lento, o outro é conhecido como o método de mudanças simples. Jie Gao e Dianjun Wang também escreveram um artigo interessante.
fonte
Esse código em python, quando chamado com
allowed_characters
definido como[0,1]
e no máximo 4 caracteres, geraria 2 ^ 4 resultados:['0000', '0001', '0010', '0011', '0100', '0101', '0110', '0111', '1000', '1001', '1010', '1011', '1100', '1101', '1110', '1111']
Espero que isso seja útil para você. Funciona com qualquer caractere, não apenas números
fonte
Aqui está um link que descreve como imprimir permutações de uma string. http://nipun-linuxtips.blogspot.in/2012/11/print-all-permutations-of-characters-in.html
fonte
Embora isso não responda exatamente à sua pergunta, aqui está uma maneira de gerar todas as permutações de letras de várias seqüências do mesmo comprimento: por exemplo, se suas palavras forem "café", "joomla" e "moodle", você pode esperar resultados como "coodle", "joodee", "joffle" etc.
Basicamente, o número de combinações é o (número de palavras) à potência de (número de letras por palavra). Portanto, escolha um número aleatório entre 0 e o número de combinações - 1, converta esse número em base (número de palavras) e use cada dígito desse número como indicador para qual palavra extrair a próxima letra.
por exemplo: no exemplo acima. 3 palavras, 6 letras = 729 combinações. Escolha um número aleatório: 465. Converta para a base 3: 122020. Pegue a primeira letra da palavra 1, 2ª da palavra 2, 3ª da palavra 2, 4ª da palavra 0 ... e você obterá "joofle".
Se você quiser todas as permutações, faça um loop de 0 a 728. Claro, se você estiver escolhendo apenas um valor aleatório, uma maneira muito
mais simples emenos confusa seria fazer um loop sobre as letras. Este método permite evitar recursões, caso você queira todas as permutações, além de fazer com que pareça que você conhece Maths (tm) !Se o número de combinações for excessivo, você poderá dividi-lo em uma série de palavras menores e concatená-las no final.
fonte
c # iterativo:
fonte
fonte
Aqui está a minha opinião sobre uma versão não recursiva
fonte
A solução pitônica:
fonte
Bem, aqui está uma solução O (n!) Elegante e não recursiva:
fonte