Cada comprimento de ciclo possível

21

Pode-se dizer que uma função (ou programa) que recebe entradas e fornece saídas possui um ciclo se a chamada da função em sua própria saída atingir repetidamente o número original. Por exemplo, tome a seguinte função:

Input:  n    1 2 3 4 5 6
Output: f(n) 5 7 1 3 4 9

Se começarmos com n=1, f(n)=5, f(f(n))=f(5)=4, f(f(f(n)))=f(4)=3, f(f(f(f(n))))=f(3)=1.

Isto está escrito (1 5 4 3). Como existem 4 números exclusivos nesse loop, esse é um ciclo de comprimento 4.


Seu desafio é escrever um programa ou função que possua ciclos de todos os comprimentos possíveis. Ou seja, deve haver um ciclo de comprimento 1, comprimento 2 e assim por diante.

Além disso, sua função / programa deve ser do número inteiro positivo para o número inteiro positivo e deve ser bijetivo , o que significa que deve haver exatamente um valor de entrada para cada valor de saída possível, sobre todos os números inteiros positivos. Dito de outra forma, a função / programa deve calcular uma permutação dos números inteiros positivos.


Detalhes: Qualquer sistema padrão de entrada / saída é permitido, incluindo STDIN, STDOUT, argumento de função, retorno, etc.

Você não precisa se preocupar com as limitações de seus tipos de dados - as propriedades acima precisam se manter apenas com a suposição de que um intou floatpode conter qualquer valor, por exemplo.

Não há restrições no comportamento da função em entradas que não sejam números inteiros positivos, e essas entradas / saídas serão ignoradas.


A pontuação é código de golfe em bytes, o código mais curto vence.

isaacg
fonte
"deve haver um ciclo de comprimento 1, de comprimento 2 e assim por diante" Se isso for interpretado como "deve haver pelo menos um ciclo de comprimento 1, pelo menos um de comprimento 2 e assim por diante" ou "deve seja exatamente um ciclo de comprimento 1, um de comprimento 2 e assim por diante ".
Bakuriu 24/07/2015
@Bakuriu Pelo menos um ciclo de cada comprimento positivo.
Isaacg

Respostas:

11

Pitão, 11 8 bytes

.<W-0zz1

Muito mais chato do que minha resposta anterior.

Todo número que contém um dígito 0 é mapeado para si mesmo. Qualquer outro número é mapeado para o número que tem seus dígitos rotacionados por 1. Portanto, por exemplo:

1 -> 1
10 -> 10
15 -> 51 -> 15
104 -> 104
123 -> 231 -> 312 -> 123
orlp
fonte
8

Python 2, 56 55 54 bytes

n=input()
a=b=1
while a+b<=n:a+=b;b+=1
print(n+~a)%b+a

Aqui estão as primeiras 21 saídas:

[1, 3, 2, 6, 4, 5, 10, 7, 8, 9, 15, 11, 12, 13, 14, 21, 16, 17, 18, 19, 20]

O padrão é óbvio se dividirmos a lista em pedaços da seguinte forma:

 1    2  3    4  5  6    7  8  9  10    11  12  13  14  15    16  17  18  19  20  21
[1]  [3, 2]  [6, 4, 5]  [10, 7, 8, 9]  [15, 11, 12, 13, 14]  [21, 16, 17, 18, 19, 20]
Sp3000
fonte
Porra, este é o padrão que eu também estava seguindo, mas com uma forma fechada.
orlp 23/07/2015
11
Interessante .. os valores a seguem a sequência A000124 . Mas acho que você já sabia disso: P
Kade
Observe que esta sequência é oeis.org/A066182 .
orlp 23/07/2015
8

Pitão, 25 bytes

+hK/*J/h@h*8tQ2 2tJ2%-QKJ

Essa é a mesma sequência que o @ Sp3000, mas com um formulário fechado. O formulário fechado é:

M (n) = piso ((1 + sqrt (1 + 8 * (n - 1))) / 2) B (n) = M (n) * (M (n) - 1) / 2 f (n) = B (n) + ((n - B (n) + 1) mod M (n))

orlp
fonte
5

Python3, 40 bytes

n=input();print([n[1:]+n[0],n]['0'in n])

Todo número que contém um dígito 0 é mapeado para si mesmo. Qualquer outro número é mapeado para o número que tem seus dígitos rotacionados por 1. Portanto, por exemplo:

1 -> 1
10 -> 10
15 -> 51 -> 15
104 -> 104
123 -> 231 -> 312 -> 123
orlp
fonte
11
Déjà vu! Legal vê-lo em dois idiomas!
Denham Coote
3

Ruby, 22 + 1 = 23

Com sinalizador de linha de comando -p, execute

~/(.)(.?)/
$_=$1+$'+$2

Quando fornecida como entrada, uma representação de seqüência de caracteres de um número (sem nova linha à direita), ele mantém o primeiro dígito constante e depois gira o restante para a esquerda, 1234tornando - se assim 1342.

Isso pode ser reduzido para 21 caracteres com $_=$1+$'+$2if/(.)(.)/, mas imprime um aviso.

histocrata
fonte
3

Ruby, 16 + 1 = 17

Com sinalizador de linha de comando -p, execute

$_=$_[/.0*$/]+$`

Essa é uma função mais complicada do que minha outra resposta, mas passa a ser mais jogável (e tolerante a seguir novas linhas). Ele pega o último dígito diferente de zero da entrada, mais os zeros à direita, e o move para o início do número. Então 9010300se torna 3009010. Qualquer número com n dígitos diferentes de zero fará parte de um ciclo de comprimento n.

Input é uma string em qualquer base via STDIN, output é uma string nessa base.

histocrata
fonte
2

Python, 43

O inverso da função do Sp3000 , implementado recursivamente.

f=lambda n,k=1:n>k and k+f(n-k,k+1)or n%k+1

A função é um ciclo seguido por dois ciclos seguidos por três ciclos, ...

(1)(2 3)(4 5 6)(7 8 9 10)(11 12 13 14 15)...

A operação n%k+1atua como um kciclo nos números 1..k. Para encontrar o apropriado kpara usar, mude tudo para baixo k=1, então k=2, e assim por diante, até n<=k.

xnor
fonte
2

Pitão, 15 bytes

A resposta mais curta até agora que usa operações numéricas em vez de operações de cadeia.

.|.&Q_=.&_=x/Q2

    Q                input
            /Q2      input div 2
           x   Q     that XOR input
          =          assign that to Q
         _           negate that
       .&       Q    that AND Q
      =              assign that to Q
     _               negate that
  .&                 input AND that
.|               Q   that OR Q

O efeito dessa função na representação binária é estender o bloco mais à direita de 1s para o próximo 0; ou, se não houver 0, redefina-o para um único 1:

10010110100000 ↦  
10010110110000 ↦  
10010110111000 ↦  
10010110111100 ↦  
10010110111110 ↦  
10010110111111 ↦
10010110100000  

Pitão, 26 bytes, variante divertida

.|.&Q_h.&/Q2+Qy=.&/Q2_h.|y

    Q                           input
         /Q2                    input div 2
             Q                  input
                  /Q2           input div 2
                         yQ     twice input
                       .|  Q    that OR input
                     _h         NOT that
                .&              (input div 2) AND that
               =                assign that to Q
              y                 twice that
            +                   input plus that
       .&                       (input div 2) AND that
     _h                         NOT that
  .&                            input AND that
.|                          Q   that OR Q

Executa a operação acima simultaneamente para todos os blocos de 1s, não apenas o mais à direita - ainda usando apenas operações bit a bit e aritmética.

1000010001001 ↦
1100011001101 ↦
1110011101001 ↦
1111010001101 ↦
1000011001001 ↦
1100011101101 ↦
1110010001001 ↦
1111011001101 ↦
1000011101001 ↦
1100010001101 ↦
1110011001001 ↦
1111011101101 ↦
1000010001001
Anders Kaseorg
fonte
1

Swift 1.2, 66 bytes

func a(b:Int){var c=0,t=1,n=b
while n>c{n-=c;t+=c++}
print(n%c+t)}
Input:  1,   2, 3,  4, 5, 6,   7, 8, 9, 10,   11, 12, 13, 14, 15
Output: 1,   3, 2,  5, 6, 4,   8, 9, 10, 7,   12, 13, 14, 15, 11
David Skrundz
fonte
1

Braquilog , 5 bytes

∋0&|↺

Experimente online!

Porto da resposta Pyth do @ orlp. Sai simples e arrumado:

∋0    % If input contains a 0 (since input is a single number, "contains" ∋ treats it as an array 
      %   of its digits, so this means "if any of input's digits are 0")
&     % Then output is the input
|     % Otherwise
↺     % Circularly shift the input once, and unify that with the output

Originalmente, eu queria portar a solução Python do Sp3000, mas isso levou 23 bytes :

⟧∋B-₁⟦++₁A≤?;A--₁;B%;A+

Experimente online!

sundar - Restabelecer Monica
fonte
0

JavaScript (ES6), 43 bytes

f=(n,i=1,j=1)=>n>j?f(n,++i,j+i):n++<j?n:n-i
Neil
fonte
0

Matlab (189)

  function u=f(n),if(~n|n==1)u=n;else,u=n;y=factor(n);z=y(y~=2);if ~isempty(z),t=y(y~=max(y));if isempty(t),u=y(end)*2^(nnz(y)-1);else,g=max(t);e=primes(g*2);u=n/g*e(find(e==g)+1);end,end,end

  • A função:

    Mapeia qualquer número inteiro de acordo com seus fatores primos; se o número for nulo ou fatorado em 2 ou 1, o número é mapeado para si mesmo; caso contrário, escolhemos o maior fator primo desse número e aumentamos os fatores primos restantes restantes pelo mais próximo fator primordial maior até atingirmos o número biggest_prime^nonde nestá a soma de todos os expoentes de todos os fatores, uma vez que atingimos esse valor, recorremos a max_prime*2^(n-1)e reproduzimos o mesmo ciclo novamente.

Abr001am
fonte
0

Matlab (137)

  function u=h(n),if(~n|n==1)u=n;else,u=n;y=factor(n);z=y(y~=2);if~isempty(z),e=nnz(y);f=nnz(z);if(~mod(e,f)&e-f)u=n/2^(e-f);else,u=u*2;end

  • Uma abordagem ligeiramente semelhante, multiplicando gradualmente qualquer número não igual a {0,1,2 ^ n} por 2até encontrarmos um expoente 2divisível pela soma dos expoentes de outros fatores primos. então passamos para o início do ciclo, dividindo por 2^(sum of exponents of other primes). os outros numbes são mapeados para si mesmos.
Abr001am
fonte