Considere uma permutação de números inteiros 1
, ... n
,, como esta para n = 6
:
[5,2,4,3,6,1]
Se você visualizar a permutação como um mapeamento de [1,2,3,4,5,6]
para [5,2,4,3,6,1]
, a permutação poderá ser descompactada em ciclos separados . Um ciclo é um subconjunto de elementos que são mapeados entre si. Por exemplo, 1
é mapeado para 5
, que é mapeado para 6
, para o qual é mapeado novamente 1
. Então, um ciclo é [1,5,6]
. Os outros ciclos são [2]
e [3,4]
. Assim, o número de ciclos para esta permutação é 3
.
Em geral, os ciclos de uma permutação são únicos (por ordem), e o número de ciclos para uma permutação de tamanho n
varia de 1
a n
.
O desafio
Dada uma permutação não vazia, produza seu número de ciclos.
A entrada é um conjunto formado pelos n
números inteiros 1
, 2
, ..., n
, onde n > 0
. Cada número inteiro ocorre exatamente uma vez. A ordem em que eles aparecem define a permutação, como no exemplo acima.
Em vez de uma matriz, você pode usar uma lista, uma sequência com um separador entre os números, uma entrada separada para cada número ou qualquer coisa que seja razoável.
Para uma permutação de tamanho n
, em vez do conjunto de números inteiros baseado em 1 1
, ..., n
você pode usar consistentemente o conjunto baseado em 0 0
, ..., n-1
. Nesse caso, indique-o na sua resposta.
O código deve funcionar por n
até 20
um tempo razoável, digamos menos de um minuto.
Código de golfe. Todos os builtins permitidos.
Casos de teste
Isso pressupõe entrada de matriz baseada em 1.
[1] -> 1
[3,2,1] -> 2
[2,3,4,5,1] -> 1
[5,2,4,3,6,1] -> 3
[8,6,4,5,2,1,7,3] -> 2
[4,5,11,12,7,1,3,9,10,6,8,2] -> 1
[4,2,5,11,12,7,1,3,9,10,6,8] -> 5
[5,8,6,18,16,9,14,10,11,12,4,20,15,19,2,17,1,13,7,3] -> 3
[14,5,17,15,10,18,1,3,4,13,11,16,2,12,9,7,20,6,19,8] -> 7
Relacionado
Esse desafio relacionado pede os ciclos reais da permutação, não o número deles. Exigir apenas o número de ciclos pode levar a algoritmos mais curtos que evitam a geração dos ciclos reais.
fonte
1
, ...,n
nessa ordem. Você pode esclarecer como um mapeamento pode ser uma entrada? É uma estrutura de dados?dict
. Eu quero ter{1: 2, 2: 1}
como uma entrada em vez de[2, 1]
.Respostas:
J, 4 bytes
Isso pressupõe que a permutação seja baseada em 0. Ele usa o built-in
C.
que, dada uma lista que representa uma permutação direta, gera uma lista de ciclos. Em seguida,#
composto@
em que retorna o número de ciclos nessa lista.Experimente aqui.
fonte
JavaScript,
9998 bytesEsta solução assume que a matriz e seus valores são indexados a zero (por exemplo
[2, 1, 0]
).Explicação
fonte
Mathematica, 45 bytes
Ele gera um gráfico e conta seus componentes conectados.
fonte
Mathematica,
372827 bytesObrigado @alephalpha por salvar 9 bytes e @miles por mais 1 byte.
fonte
PermutationCycles[#,Length]&
PermutationCycles
poderia usar um segundo argumento para alterar a cabeça de sua saída. Você também pode usar a notação infix para salvar outro byte#~PermutationCycles~Length&
.#&
é um pouco menor queIdentity
. ;)Python,
776967 bytesfonte
(not p[i-1])
pode ser feito como0**p[i-1]
Geléia,
12109 bytesGuardou 1 byte graças a @ Dennis .
Isso usa permutações baseadas em 1. Ele funciona aplicando a permutação repetidamente até atingir uma permutação anterior, mantendo também seus valores anteriores. Ao acompanhar as alterações, ele criará a órbita para cada valor ao longo das colunas dessa tabela. Em seguida, localizando o mínimo ou o máximo de cada coluna, um rótulo para esse ciclo pode ser criado. Em seguida, desduplique essa lista de rótulos e obtenha o comprimento, que será o número de ciclos disjuntos.
Experimente aqui.
Explicação
fonte
ị³$ÐĿ«/QL
Deveria trabalhar.Python, 64 bytes
Esse código golfado é idiomático e legível. Usa indexação 0.
Cada valor examina o que aponta e o que o valor apontado aponta e aponta para o menor dos dois. Após repetições suficientes, cada elemento aponta para o menor elemento do seu ciclo. O número de elementos distintos apontados é o número de ciclos.
Basta fazer
n
iterações. Como alternativa, poderíamos iterar até que a lista não seja mais alterada. Essa estratégia me deu uma função recursiva do mesmo comprimento, 64 bytes:A redução foi de 65 bytes
As
set(_)
conversões podem ser reduzidas para{*_}
Python 3.5, economizando 2 bytes.fonte
Haskell, 111 bytes
Usa indexação baseada em 0
fonte
1l!i|iIi!!1ll1|
Pitão, 9 bytes
Usa índices baseados em 0. Experimente online .
Como funciona
fonte
JavaScript (ES6), 49 bytes
Usa indexação baseada em zero. Explicação:
reduce
é usado para chamar a função internag
em cada elemento da matriz.c
é a contagem de ciclos,e
é o elemento da matriz,i
é o índice da matriz. Se o elemento for menor que o índice, é um ciclo em potencial - o elemento é usado para indexar na matriz para encontrar recursivamente o próximo elemento no ciclo. Se começamos ou terminamos com o índice original, esse é um novo ciclo e incrementamos a contagem de ciclos. Se a qualquer momento encontrarmos um valor maior que o índice, contaremos esse ciclo posteriormente.fonte
[2,1,0,3,4,5]
, ele falhou com esta mensagem "Tamanho máximo da pilha de chamadas excedido".C, 90 bytes
Chame
f()
com umaint
matriz mutável , indexação baseada em 1. O segundo parâmetro é o tamanho da matriz. A função retorna o número de ciclos.Experimente em ideone .
O algoritmo:
fonte
GAP , 30 bytes
Simplesmente, o segundo argumento para
Cycles
fornece o conjunto no qual a permutação deve atuar:fonte