Calculer le super-logarithme


29

Cela devrait être un simple défi.

Étant donné un nombre n >= 0, sortez le super-logarithme (ou le log *, log-star ou logarithme itéré , qui sont équivalents car nn'est jamais négatif pour ce défi.) De n.

log * (n): = {0 si n <= 1;  1 + log * (log (n)) si n> 1}

Il s'agit de l'une des deux fonctions inverses de la tétration . L'autre est la super-racine , qui est dans une question connexe .

Exemples

Input       Output
0           0
1           0
2           1
3           2
4           2
...
15          2
16          3
...
3814279     3
3814280     4

Règles

  • Vous n'avez pas besoin de prendre en charge les décimales, bien que vous puissiez le faire.
  • Vous devez au moins prendre en charge la saisie 3814280 = ceiling(e^e^e).
  • Vous ne pouvez pas coder en dur les valeurs comme 3814280. (Votre programme doit théoriquement prendre en charge des nombres plus élevés.) Je veux qu'un algorithme soit implémenté.
  • Le code le plus court gagne.

OEIS connexes


Réponses:


14

Gelée , 8 octets

ÆlÐĿĊḊi1

Essayez-le en ligne! ou vérifiez tous les cas de test .

Contexte

Nous commençons par prendre successivement les logarithmes naturels de l'entrée et des résultats suivants jusqu'à ce que le résultat ne change plus. Cela fonctionne parce que l'extension du logarithme naturel au plan complexe a un point fixe ; si z = e -W (-1) ≈ 0,318 + 1,337i - où W désigne le fonction Lambert W - nous avons log (z) = z .

Pour l'entrée n , après avoir calculé [n, log (n), log (log (n)),…, z] , nous appliquons d'abord la fonction de plafond à chacun des résultats. L'implémentation de Jelly ( Ċ) calcule en fait la partie imaginaire du nombre complexe , mais cela ne nous intéresse pas de toute façon.

Une fois que la k ème application de log donne une valeur inférieure ou égale à 1 , Ċrenvoie 1 pour la première fois. L'index basé sur 0 de ce premier 1 est le résultat souhaité.

L'implémentation simple (calcul de l'index basé sur 1, décrémentation) échoue en raison du cas de bord 0 , qui n'a pas de 1 dans sa liste de logarithmes. En fait, pour l'entrée 0 , la séquence de logarithmes est

[0, None]

C'est parce que le logarithme de Jelly ( Æl) est surchargé; il essaie d'abord math.log(logarithme réel), puis cmath.log(logarithme complexe), et finalement "abandonne" et revient None. Heureusement, il Ċest également surchargé et renvoie simplement son argument s'il ne peut pas arrondir ou prendre une partie imaginaire.

De même, l'entrée 1 renvoie

[1, 0, None]

ce qui peut créer des problèmes dans d'autres approches qui impliquent ou non Ċ.

Une façon de résoudre ce problème est d'appliquer (retirer la file d'attente; supprime le premier élément) au tableau de logarithmes. Cette carte

0ÆlÐĿ -> [0, None]    -> [None]
1ÆlÐĿ -> [1, 0, None] -> [0, None]

donc aucune des listes n'a un 1 maintenant. De cette façon, trouver l'index du premier 1 retournera 0 (non trouvé), qui est la sortie souhaitée pour les entrées 0 et 1 .

Comment ça marche

ÆlÐĿĊḊi1  Main link. Argument: n (non-negative integer)

  ÐĿ      Apply the following link until the results are no longer unique.
Æl          Natural logarithm.
          Return the array of all unique results.
    Ċ     Round all resulting real numbers up to the nearest integer. This takes
          the imaginary part of complex numbers and does nothing for non-numbers.
     Ḋ    Dequeue; remove the first item (n) of the array of results.
      i1  Find the first index of 1 (0 if not found).

C'est l'un des trois seuls atomes de Jelly qui sont surchargés de manière non évidente.


11

Gelée , 9 octets

Æl>1$пL’

Essayez-le en ligne!

Suite de tests.(Légèrement modifié.)

Explication

Æl>1$пL’
     п    while loop, collect all intermediate results.
  >1$      condition: z>1
Æl         body: natural logarithm.
       L   length of the array containing all intermediate results,
           meaning number of iterations
        ’  minus one.


7

Javascript, 45 27 26 octets

l=a=>a>1&&1+l(Math.log(a))

Voici la suite de tests (3e rév)

Merci à @LeakyNun d'avoir enregistré 1 octet avec la fonction conditionnelle, puis de convertir la fonction en lambda, et @Neil pour avoir indiqué faux est une valeur de retour correcte pour <= 1 (le test a été changé en == au lieu de ===)


Je le faisais sans es6, mais oui, ce serait un octet plus court, merci.
CShark

Pourquoi n'utiliseriez-vous pas lambda?
Leaky Nun

pas de bonne raison, je ne l'ai pas beaucoup utilisé, donc ce n'est pas mon premier instinct
CShark

Apparemment, nous sommes autorisés à retourner falseau lieu de 0 (car il se convertit automatiquement en 0 dans une expression entière), auquel cas vous pouvez supprimer le |0.
Neil

Cela permettrait d'économiser 1 octet, mais que voulez-vous dire par "il se convertit automatiquement en 0"? Qu'Est-ce que c'est"?
CShark

6

Mathematica, 21 octets

If[#>1,1+#0@Log@#,0]&

Fonction anonyme récursive. Prend un entier en entrée et renvoie son super-logarithme en sortie. Utilise simplement la définition donnée.


3
En fait, j'ai regardé à l'avance pour voir s'il y avait un intégré. J'ai été surpris quand il n'y en avait pas. : D
mbomb007



5

Haskell, 23 octets

l x|x>1=1+l(log x)|1<2=0

Exemple d'utilisation: l 3814280-> 4.


4

Python 3, 45 octets

import math
s=lambda x:x>1and-~s(math.log(x))

Pour x <= 1, cela renvoie False(qui est == 0en Python).


Oui, Falsepeut être utilisé pour 0.
mbomb007

De plus, vous avez battu mon implémentation naïve (en utilisant andplutôt qu'en if else). Grats.
mbomb007

4

05AB1E, 16 13 octets

[Dî2‹#¼žr.n]¾

Explication

              # implicit input n
[          ]  # infinite loop
 Dî2‹#        # break if n rounded up is less than 2
      ¼       # else, increase counter
       žr.n   # set next n = log(n)
            ¾ # push counter and implicitly print

Essayez-le en ligne


3

MATL , 15 12 octets

0`ZetG>~}x@q

Essayez-le en ligne! Ou vérifiez tous les cas de test (version légèrement modifiée pour gérer plusieurs entrées).

Comment ça marche

En commençant par 0, appliquez l'exponentiation itérée jusqu'à dépasser l'entrée. La sortie est le nombre d'itérations moins 1.

0       % Push 0
`       % Do...while loop
  Ze    %   Exponential
  t     %   Duplicate
  G     %   Push input
  >~    %   Is current value less than or equal to the input? If so: next iteration
}       % Finally (code executed at the end of the last iteration)
  x     %   Delete
  @q    %   Iteration index minus 1
        % Implicitly end loop
        % Implicitly display stack

3

J , 21 19 18 16 octets

Enregistré 2 octets à Leaky Nun, 1 octet à Galen Ivanov et 2 octets à FrownyFrog!

2#@}.(0>.^.)^:a:

Essayez-le en ligne!

Cas de test

ls =: >:@$:@^.`0:@.(<:&1)
   ls 0
0
   ls 1
0
   ls 2
1
   ls 3
2
   ls 4
2
   ls 15
2
   ls 16
3
   ls 3814280
4

Voici ma solution de 18 octets: 2#@}.^.^:(0<])^:a:(J'ai commencé à résoudre ce qui s'est avéré être un dup de ce problème.)
Galen Ivanov

2#@}.(0>.^.)^:a:semble fonctionner.
FrownyFrog

Je ne sais pas si c'est équivalent cependant.
FrownyFrog


2

MATLAB / Octave, 44 octets

function a=g(n);a=0;if n>1;a=1+g(log(n));end

J'ai essayé de tout faire comme une fonction anonyme, mais j'ai oublié que MATLAB / Octave continue d'évaluer les expressions même si elles sont multipliées par une valeur booléenne fausse (zéro):

f=@(n)(n>1)*(1+f(log(n)))


Oui, ce serait bien d'avoir un produit en court-circuit :-)
Luis Mendo

2

R, 38 37 octets

f=function(x)if(x>1)1+f(log(x))else 0

Merci @ user5957401 pour l'octet supplémentaire!

Cas de test:

> f(0)
[1] 0
> f(1)
[1] 0
> f(2)
[1] 1
> f(3)
[1] 2
> f(4)
[1] 2
> f(3814279)
[1] 3
> f(3814280)
[1] 4

Je pense que vous pouvez enregistrer un octet en utilisant une instruction littérale if, else. c'est à dire if(x>1)1+f(log(x))else 0est un octet plus court.
user5957401

2

R , 34 octets

f=pryr::f(`if`(n>1,1+f(log(n)),0))

Essayez-le en ligne!

Une approche non récursive est possible: 36 octets et prend l'entrée de stdin.

n=scan()
while((n=log(n))>0)F=F+1
+F

2

Java 7, 47 octets

int c(double n){return n>1?1+c(Math.log(n)):0;}

Essayez-le en ligne.

La méthode récursive de style Java 7 ci-dessus est plus courte de 2 octets qu'une lambda itérative de style Java 8:

n->{int c=0;for(;n>1;c++)n=Math.log(n);return c;}

Essayez-le en ligne.

Explication:

int c(double n){      // Method with double parameter and integer return-type
  return n>1?         //  If the input is larger than 1:
    1+                //   Return 1 +
      c(Math.log(n))  //   A recursive call with log(input)
   :                  //  Else:
    0;                //   Return 0 instead

n->{                  // Method with double parameter and integer return-type
  int c=0;            //  Create a counter, starting at 0
  for(;n>1;           //  Loop as long as the input is still larger than 1:
    c++)              //   Increase the counter by 1
    n=Math.log(n);    //   And update the input to log(input)
  return c;}          //  After the loop: return the counter as result

Vous pourriez le raccourcir avec un lambda Java 8.
mbomb007

@ mbomb007 répondant trois ans plus tard, haha ​​.. (à l'époque je ne faisais que jouer au golf en code dans Java 7), mais pour répondre à votre question: non, malheureusement, un lambda Java 8 fait 2 octets de plus que la méthode récursive. Je l'ai ajouté à ma réponse et j'ai également ajouté une explication.
Kevin Cruijssen

Vous ne pouvez donc pas faire de lambdas récursifs?
mbomb007

@ mbomb007 Non, malheureusement pas à Java. En Python, JavaScript et je pense que C # .NET aussi, les lambdas récursifs sont possibles, mais en Java pas pour une raison quelconque.
Kevin Cruijssen

1

Emacs Lisp, 38 octets

(defun l(n)(if(> n 1)(1+(l(log n)))0))

Testcases:

(mapcar 'l '(0 1 2 3 4 15 16 3814279 3814280))
;; (0 0 1 2 2 2 3 3 4)

1

Gelée , 8 octets

-Ælß$Ị?‘

Mise en œuvre simple de la définition. Essayez-le en ligne! ou vérifier tous les cas de test .

Comment ça marche

-Ælß$Ị?‘  Main link. Argument: x

     Ị    Insignificant; test if |x| ≤ 1.
      ?   If the result is 1:
-           Return -1.
          Else:
   $        Execute the monadic chain formed by the two links to the left.
Æl            Apply natural logarithm to x.
  ß           Recursively call the main link.
       ‘  Increment the result.

1

Perl 5, 35 octets

Très simple, nécessite -M5.016(qui est gratuit) d'activer le __SUB__mot - clé pour la récursivité anonyme.

sub{$_[0]>1?1+__SUB__->(log pop):0}

Une autre alternative est

sub{$_[0]>1?1+__SUB__->(log pop):0}

qui est de 34 octets, et donne la même sortie pour toutes les entrées> 1, mais renvoie la valeur fausse spéciale pour les entrées <= 1. False est numériquement égal à zéro, mais s'affiche comme "" (chaîne vide), donc il ne le fait probablement pas '' t qualifier.


Très bonne réponse. Vous pouvez gagner 1 octet en faisant sub{($_=pop)>1?1+__SUB__->(log):0}cependant
Dada

1

CJam (16 octets)

rd{_1>}{_ml}w],(

Démo en ligne

Boucle simple avec pré-condition. (Ce que je veux vraiment ici, c'est une opération de dépliage de style Golfscript, mais CJam n'en a pas, et la virgule flottante dans GolfScript est désordonnée et pas du tout golfy).


En passant, ceci est ma 80e réponse en mathématiques et m'a valu mon deuxième badge tag aujourd'hui.
Peter Taylor


1

Raquette, 61 octets

(λ(x)(letrec([a(λ(b)(if(> b 1)(+ 1 (a(log b)))0))])(a x)))

1

Érable, 32,30 29 octets

f:=x->`if`(x>1,1+f(log(x)),0)

Cas de test:

> f(0.);
  0
> f(1.);
  0
> f(2.);
  1
> f(3.);
  2
> f(4.);
  2
> f(3814279.);
  3
> f(3814280.);
  4

1

R, 36 octets

Approche légèrement différente de Plannapus

->n;a=0;while(n>1){a=a+1;n=log(n)};a

Utilise une affectation à droite pour exécuter le code - le numéro souhaité doit donc le précéder. c'est à dire

10->n;a=0;while(n>1){a=a+1;n=log(n)};a

0

Mathematica, 29 octets

Simple comme l'enfer, et fonctionne pour les entrées comiques et négatives:

f[x_]:=If[x>1,1+f[Log[x]],0]

enter image description here



0

Perl 6 , 21 octets

{($_,*.log...1>=*)-1}

Essayez-le en ligne!

L'expression entre parenthèses est une séquence. $_, l'argument de la fonction, est le premier élément. *.loggénère chaque élément successif en prenant le log de l'élément précédent. La séquence continue jusqu'à ce que la condition de fin,, 1 >= *soit vraie: 1 est supérieur ou égal à l'élément courant. Soustraire 1 de la séquence le contraint à un nombre: sa longueur.

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.