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

mbomb007
la source
En relation.
Oliver Ni

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.

Dennis
la source
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.
Leaky Nun
la source
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 ===)

CShark
la source
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.

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

Pyth, 10 octets

L&>b1hy.lb

Suite de tests.

Cela définit une fonction.

Leaky Nun
la source
Je ne vois aucune sortie dans votre suite de tests. Juste un tas de lignes vides dans la sortie.
mbomb007
@ mbomb007 Fixé.
Leaky Nun
Way cooler: tl.u?>N1.l;-)
Jakube
@Jakube Vous pouvez poster ça!
Leaky Nun
5

Haskell, 23 octets

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

Exemple d'utilisation: l 3814280-> 4.

nimi
la source
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).

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

Emigna
la source
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
Luis Mendo
la source
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
Conor O'Brien
la source
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)))

costrom
la source
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
plannapus
la source
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
rturnbull
la source
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
Kevin Cruijssen
la source
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)
Lord Yuuma
la source
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.
Dennis
la source
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.

Hobbs
la source
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).

Peter Taylor
la source
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

PARI / GP , 24 octets

Juste la récursivité simple.

f(n)=if(n>1,1+f(log(n)))
Charles
la source
1

Raquette, 61 octets

(λ(x)(letrec([a(λ(b)(if(> b 1)(+ 1 (a(log b)))0))])(a x)))
Steven H.
la source
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
DSkoog
la source
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
user5957401
la source
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

Landak
la source
0

Rubis, 29 octets

l=->n{n<=1?0:1+l[Math.log n]}
Seims
la source
-1 octet en réécrivant n<=1?a:bas n>1?b:aet -1 octet supplémentaire avec des fonctions lambda anonymes .
Simply Beautiful Art
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.

Sean
la source