Chaque longueur de cycle possible

21

Une fonction (ou un programme) qui prend des entrées et fournit des sorties peut être considérée comme ayant un cycle si l'appel de la fonction sur sa propre sortie à plusieurs reprises atteint finalement le numéro d'origine. Par exemple, prenez la fonction suivante:

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

Si nous commençons par 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.

C'est écrit (1 5 4 3). Puisqu'il y a 4 nombres uniques dans cette boucle, c'est un cycle de longueur 4.


Votre défi est d'écrire un programme ou une fonction qui a des cycles de toutes les longueurs possibles. Autrement dit, il doit y avoir un cycle de longueur 1, de longueur 2, etc.

De plus, votre fonction / programme doit aller des entiers positifs aux entiers positifs, et il doit être bijectif , ce qui signifie qu'il doit y avoir exactement une valeur d'entrée pour chaque valeur de sortie possible, sur tous les entiers positifs. En d'autres termes, la fonction / programme doit calculer une permutation des entiers positifs.


Détails: Tout système d'entrée / sortie standard est autorisé, y compris STDIN, STDOUT, argument de fonction, retour, etc. Les failles standard sont interdites.

Vous n'avez pas à vous soucier des limites de vos types de données - les propriétés ci-dessus ne doivent être conservées qu'en supposant qu'une intou floatpeut contenir n'importe quelle valeur, par exemple.

Il n'y a aucune restriction sur le comportement de la fonction sur les entrées qui ne sont pas des entiers positifs, et ces entrées / sorties seront ignorées.


La notation est le golf de code en octets, le code le plus court gagne.

isaacg
la source
"il doit y avoir un cycle de longueur 1, de longueur 2, etc." Si cela doit être interprété comme "il doit y avoir au moins un cycle de longueur 1, au moins un de longueur 2, etc." ou "il doit y avoir être exactement un cycle de longueur 1, un de longueur 2, etc. ".
Bakuriu
@Bakuriu Au moins un cycle de chaque longueur positive.
isaacg

Réponses:

11

Pyth, 11 8 octets

.<W-0zz1

Beaucoup plus ennuyeux que ma réponse précédente.

Chaque numéro contenant un chiffre à 0 correspond à lui-même. Tout autre numéro correspond au numéro dont les chiffres tournent de 1. Ainsi, par exemple:

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

Python 2, 56 55 54 octets

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

Voici les 21 premières sorties:

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

Le modèle est évident si nous divisons la liste en morceaux comme ceci:

 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
la source
Merde, c'est le modèle que j'allais aussi, mais avec une forme fermée.
orlp
1
Intéressant .. les valeurs a suivent la séquence A000124 . Mais je suppose que vous le saviez déjà: P
Kade
Notez que cette séquence est oeis.org/A066182 .
orlp
8

Pyth, 25 octets

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

Il s'agit de la même séquence que @ Sp3000, mais avec un formulaire fermé. Le formulaire fermé est:

M (n) = étage ((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
la source
5

Python3, 40 octets

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

Chaque numéro contenant un chiffre à 0 correspond à lui-même. Tout autre numéro correspond au numéro dont les chiffres tournent de 1. Ainsi, par exemple:

1 -> 1
10 -> 10
15 -> 51 -> 15
104 -> 104
123 -> 231 -> 312 -> 123
orlp
la source
1
Déjà vu! Cool de le voir en deux langues!
Denham Coote
3

Rubis, 22 + 1 = 23

Avec l'indicateur de ligne de commande -p, exécutez

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

Lorsqu'il est donné en entrée une représentation sous forme de chaîne d'un nombre (sans retour à la ligne), il maintient le premier chiffre constant, puis fait pivoter le reste à gauche, ainsi 1234devient 1342.

Cela peut être réduit à 21 caractères avec $_=$1+$'+$2if/(.)(.)/, mais affiche un avertissement.

histocrate
la source
3

Rubis, 16 + 1 = 17

Avec l'indicateur de ligne de commande -p, exécutez

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

C'est une fonction plus compliquée que mon autre réponse, mais s'avère plus jouable au golf (et tolérante aux nouvelles lignes). Il prend le dernier chiffre non nul de l'entrée, plus les zéros de fin, et le déplace au début du nombre. Devient 9010300ainsi 3009010. Tout nombre avec n chiffres non nuls fera partie d'un cycle de n longueurs.

L'entrée est une chaîne dans n'importe quelle base via STDIN, la sortie est une chaîne dans cette base.

histocrate
la source
2

Python, 43

L' inverse de la fonction du Sp3000 , implémenté récursivement.

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

La fonction est un cycle suivi d'un cycle deux suivi d'un cycle trois, ...

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

L'opération n%k+1agit comme un kcycle sur les nombres 1..k. Pour trouver ce qui convient kà utiliser, déplacez tout vers le bas par k=1, puis k=2, et ainsi de suite, jusqu'à n<=k.

xnor
la source
2

Pyth, 15 octets

La réponse la plus courte à ce jour qui utilise des opérations numériques plutôt que des opérations de chaîne.

.|.&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

L'effet de cette fonction sur la représentation binaire est d'étendre le bloc de 1s le plus à droite dans le 0 suivant; ou s'il n'y a pas de 0, pour le réinitialiser à un seul 1:

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

Pyth, 26 octets, variante amusante

.|.&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

Effectue l'opération ci-dessus simultanément sur tous les blocs de 1, pas seulement sur celui de droite, en n'utilisant toujours que des opérations binaires et arithmétiques.

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

Swift 1.2, 66 octets

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
la source
1

Brachylog , 5 octets

∋0&|↺

Essayez-le en ligne!

Port de la réponse Pyth de @ orlp. Sort simple et soigné:

∋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

Je voulais à l'origine porter la solution Python de @ Sp3000, mais cela a pris 23 octets :

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

Essayez-le en ligne!

Sundar - Rétablir Monica
la source
0

JavaScript (ES6), 43 octets

f=(n,i=1,j=1)=>n>j?f(n,++i,j+i):n++<j?n:n-i
Neil
la source
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

  • La fonction:

    Mappe tout entier en fonction de ses facteurs premiers, si le nombre est nul ou factorisé en 2 ou 1, le nombre est mappé sur lui-même, sinon nous choisissons le plus grand facteur premier de ce nombre, puis nous incrémentons les différents facteurs premiers restants du plus proche plus grand facteur premier jusqu'à ce que nous atteignions le nombre biggest_prime^nnest la somme de tous les exposants de tous les facteurs, une fois que nous atteignons ce montant, nous nous tournons vers max_prime*2^(n-1)et nous reproduisons à nouveau le même cycle.

Abr001am
la source
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

  • Une approche légèrement similaire, multipliant progressivement tout nombre non égal à {0,1,2 ^ n} par 2jusqu'à ce que nous tombions sur un exposant 2qui est divisible par la somme des exposants d'autres facteurs premiers. nous passons ensuite au début du cycle en divisant par 2^(sum of exponents of other primes). les autres engourdis sont mappés sur eux-mêmes.
Abr001am
la source