Estou tentando escrever uma função que faça o seguinte:
- aceita uma matriz de números inteiros como argumento (por exemplo, [1,2,3,4])
- cria uma matriz de todas as permutações possíveis de [1,2,3,4], com cada permutação tendo um comprimento de 4
a função abaixo (achei on-line) faz isso usando uma string como argumento e retornando todas as permutações dessa string
Não consegui descobrir como modificá-lo para fazê-lo funcionar com uma matriz de números inteiros (acho que isso tem algo a ver com a maneira como alguns dos métodos funcionam de maneira diferente em cadeias de caracteres do que em inteiros, mas não tenho certeza. ..)
var permArr = [], usedChars = [];
function permute(input) {
var i, ch, chars = input.split("");
for (i = 0; i < chars.length; i++) {
ch = chars.splice(i, 1);
usedChars.push(ch);
if (chars.length == 0)
permArr[permArr.length] = usedChars.join("");
permute(chars.join(""));
chars.splice(i, 0, ch);
usedChars.pop();
}
return permArr
};
Nota: Estou procurando fazer com que a função retorne matrizes de números inteiros , não uma matriz de seqüências de caracteres .
Eu realmente preciso que a solução esteja em JavaScript. Eu já descobri como fazer isso em python
fonte
Um pouco tarde, mas gostaria de adicionar uma versão um pouco mais elegante aqui. Pode ser qualquer matriz ...
Adicionando uma versão do ES6 (2015). Também não altera a matriz de entrada original. Funciona no console do Chrome ...
Assim...
Rendimentos...
E...
Rendimentos...
fonte
var results = new Array(factorial(inputArr.length)), length=0
, em seguida, substituirresults.push(…)
comresults[length++]=…
var cur, memo = memo || [];
faz?slice()
depermute(curr.slice(), m.concat(next))
realmente necessário?O algoritmo muito eficiente a seguir usa o método Heap para gerar todas as permutações de elementos N com complexidade de tempo de execução em O (N!):
O mesmo algoritmo implementado como um gerador com complexidade de espaço em O (N):
Mostrar snippet de código
Comparação de desempenho
Sinta-se à vontade para adicionar sua implementação ao seguinte conjunto de testes benchmark.js :
Mostrar snippet de código
Resultados em tempo de execução do Chrome 48:
fonte
yield permutation.slice()
lo se não cortar, apenas obtém a última permutação calculada.fonte
.filter(uniq)
no resultado.[1,2,3].length == 3 && "foo" || "bar"
ou[1,2].length == 3 && "foo" || "bar"
oh meu! Há sim!(or (and (= 3 2) (print "hello!")) (print "goodbye"))
Eu melhorei a resposta de SiGanteng .
Agora é possível ligar
permute
mais de uma vez, porquepermArr
eusedChars
são limpos sempre.Mostrar snippet de código
fonte
A função a seguir permite uma matriz de qualquer tipo e chama uma função de retorno de chamada especificada em cada permutação encontrada:
Se você chamar assim:
Eu acho que ele fará exatamente o que você precisa - preencha uma matriz chamada
result
com as permutações da matriz [1, 2, 3]. O resultado é:Código ligeiramente mais claro no JSFiddle: http://jsfiddle.net/MgmMg/6/
fonte
A maioria das respostas a essa pergunta usa operações caras, como inserções e exclusões contínuas de itens em uma matriz ou copiar matrizes reiterativamente.
Em vez disso, esta é a solução típica de retorno:
Como a matriz de resultados será enorme, pode ser uma boa idéia iterar os resultados um por um, em vez de alocar todos os dados simultaneamente. No ES6, isso pode ser feito com geradores:
fonte
Essa é uma tarefa interessante e aqui está minha contribuição. É muito simples e rápido. Se estiver interessado, tenha paciência comigo e continue a ler.
Se você deseja um trabalho rápido, você definitivamente precisa se envolver em programação dinâmica. O que significa que você deve esquecer as abordagens recursivas. Isso é certeza...
Está bem O código do le_m que usa o método Heap parece ser o mais rápido até agora. Bem, eu não tenho um nome para o meu algoritmo, não sei se ele já foi implementado ou não, mas é muito simples e rápido. Como em todas as abordagens de programação dinâmica, começaremos com o problema mais simples e buscaremos o resultado final.
Assumindo que temos uma matriz
a = [1,2,3]
, começaremos comDepois siga estes três passos;
r
matriz (resultado), adicionaremos o próximo item da matriz de entrada.t
. (bem, exceto o primeiro a não perder tempo com rotação 0)r
matriz provisória,t
devemos manter o próximo nível de resultados, para quer = t; t = [];
continuemos até o comprimento da matriz de entrada.a
.Portanto, a seguir estão nossos passos;
Então aqui está o código
Em vários testes, eu vi resolver 120 permutações de [0,1,2,3,4] por 2000 vezes em 25 ~ 35ms.
fonte
rotatePerm
(o acima) é consistentemente 1,2 mais rápido. Com o FF não há consistência. Após vários testes, às vezesheapPerm
é 2 vezes mais rápido, algumas vezes,rotatePerm
é 1,1 vezes mais rápido. Com outros navegadores de kit da web, como Opera ou Epiphany, o sistema érotatePerm
constantemente 1,1 vezes mais rápido. No entanto, o EdgeheapPerm
é consistentemente 1,2 vezes mais rápido a cada vez.permutations
função :)Alguma versão inspirada em Haskell:
fonte
Responda sem a necessidade de uma matriz externa ou função adicional
fonte
Atualmente, a versão mais rápida, mais eficiente (resistente) e mais elegante (2020)
fonte
len % 2 // parity dependent adjacent elements swap
significa e por que é usado?Aqui está uma solução legal
fonte
Aqui está outra solução "mais recursiva".
Resultado:
fonte
Teste com:
fonte
A maioria das outras respostas não utiliza as novas funções de gerador de javascript, que são uma solução perfeita para esse tipo de problema. Você provavelmente só precisa de uma permutação de cada vez na memória. Além disso, prefiro gerar uma permutação de um intervalo de índices, pois isso permite que eu indexe cada permutação e pule diretamente para qualquer permutação específica, além de ser usado para permutar qualquer outra coleção.
fonte
fonte
Aqui está um que eu fiz ...
E aqui está de novo, mas escrito de forma menos concisa! ...
Como funciona: se a matriz tiver mais de um elemento, ela percorre cada elemento e a concatena com uma chamada recursiva para si mesma com os elementos restantes como argumento. Não muda a matriz original.
fonte
Resposta funcional usando flatMap:
fonte
Saídas permutações lexicograficamente ordenadas. Funciona apenas com números. Em outro caso, você deve alterar o método de troca na linha 34.
fonte
Semelhante em espírito à solução no estilo Haskell da @crl, mas trabalhando com
reduce
:fonte
Este é um caso de uso muito bom para mapear / reduzir:
[].concat(cv,a)
fonte
Aqui está uma versão mínima do ES6. O achatar e sem funções pode ser retirado do Lodash.
Resultado:
fonte
fonte
fonte
Muito tarde. Ainda assim, caso isso ajude alguém.
fonte
Eu tive uma falha ao criar uma versão disso que tenta ser uma programação concisa, porém legível e puramente funcional.
Observe que a formatação do argumento transforma uma sequência de entrada em uma matriz. Não tenho certeza se isso é um pouco mágico demais . Não tenho certeza se eu já vi isso na natureza. Para legibilidade real, eu provavelmente faria
input = [...input]
a primeira linha da função.fonte
Esta é uma implementação do algoritmo do Heap (semelhante ao @ le_m), exceto que é recursiva.
Parece que também é muito mais rápido: https://jsfiddle.net/3brqzaLe/
fonte
Minha primeira contribuição para o site. Além disso, de acordo com os testes que eu fiz, esse código é executado mais rapidamente do que todos os outros métodos mencionados aqui antes desta data; é claro que é mínimo se houver poucos valores, mas o tempo aumenta exponencialmente ao adicionar muitos.
fonte
Eu escrevi um post para demonstrar como permutar uma matriz em JavaScript. Aqui está o código que faz isso.
Apenas ligue
vai funcionar. Para detalhes sobre como isso funciona, consulte a explicação nesse post.
fonte
fonte