计算超级对数


29

这应该是一个简单的挑战。

给定一个数字n >= 0,输出的超级对数(或log *,log-star或迭代对数,它们是等效的,因为n对于该挑战永远不会为负。)n

log *(n):= {如果n <= 1则为0;  1 + log *(log(n))如果n> 1}

这是官能的两个反函数之一。另一个是超级根,这是一个相关的问题

例子

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

规则

  • 您可能不需要支持小数。
  • 您需要至少支持输入3814280 = ceiling(e^e^e)
  • 您可能不对值进行硬编码3814280。(理论上,您的程序必须支持更高的数字。)我希望实现一种算法。
  • 最短的代码胜出。

相关OEIS


Answers:


14

果冻,8 字节

ÆlÐĿĊḊi1

在线尝试!验证所有测试用例

背景

我们从连续获取输入和随后结果的自然对数开始,直到结果不再改变为止。之所以有效,是因为自然对数到复平面的扩展有一个不动点 ; 如果z = e -W(-1) ≈0.318 + 1.337i –其中W表示Lambert W函数 –我们有log(z)= z

对于输入n,在计算[n,log(n),log(log(n)),…,z]之后,我们首先将上限函数应用于每个结果。果冻的实现(Ċ)实际计算的虚部复杂的号码,而不是,但我们无法在这些反正感兴趣。

一旦ķ 的应用程序日志产生一个值小于或等于1Ċ将返回1首次。该第一个1的从0开始的索引是所需的结果。

直接实现(基于计算1的索引,递减)由于边缘情况0失败,对数情况0的对数列表中没有1。实际上,对于输入0,对数序列为

[0, None]

这是因为Jelly的对数(Æl)已重载;它首先尝试math.log(实对数),然后尝试(cmath.log复数对数),最后“放弃”并返回None。幸运的是,Ċ类似地重载了它,如果它不能四舍五入或没有想象的部分,则只返回它的参数。

同样,输入1返回

[1, 0, None]

这可能在其他涉及或不涉及的方法中产生问题Ċ

解决此问题的一种方法是对对数数组应用(出队;删除第一个元素)。这个地图

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

所以现在两个列表都没有1。这样,找到第一个1的索引将返回0(未找到),这是输入01的期望输出。

怎么运行的

Æ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).

这是果冻中仅有的三个以非显而易见的方式超载的原子之一。


11

果冻,9字节

Æl>1$пL’

在线尝试!

测试套件。(稍作修改。)

说明

Æ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字节

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

这是测试套件(第3版)

感谢@LeakyNun有条件地保存1个字节,然后将函数转换为lambda,而@Neil指出false则可以返回<= 1(将测试更改为==而不是===)


我是在没有es6的情况下执行此操作的,但是,是的,它要短1个字节,谢谢。
CShark '16

为什么不使用lambda?
Leaky Nun

没有充分的理由,我只是没有太多使用它,所以这不是我的本能
CShark

显然,我们允许返回false而不是0(因为它会在整数表达式中自动转换为0),在这种情况下,您可以删除|0
尼尔

那将节省1个字节,但是“它自动转换为0”是什么意思?它是什么”?
CShark

6

Mathematica,21个字节

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

递归匿名函数。以整数作为输入并返回其超对数作为输出。只使用给定的定义。


3
我实际上提前看了看是否有内置的。没有的时候我很惊讶。:D
mbomb007 '16



5

Haskell,23个字节

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

用法示例:l 3814280-> 4


4

Python 3,45个字节

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

对于x <= 1,这将返回False== 0在Python中)。


是的,False可以用于0
mbomb007 '16

另外,您击败了我的天真的实现(使用and而不是if else)。。
mbomb007 '16

4

05AB1E,16 13字节

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

说明

              # 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

在线尝试


3

MATL15 12字节

0`ZetG>~}x@q

在线尝试!验证所有测试用例(略作修改的版本以处理多个输入)。

怎么运行的

从0开始,应用迭代幂运算直到超过输入。输出为迭代次数减去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



2

MATLAB /八度,44字节

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

试图将其作为一个匿名函数完成所有操作,但是我忘记了即使MATLAB / Octave乘以布尔假(零)值,它们仍会继续求值:

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


是的,最好有一个短路产品:-)
Luis Mendo

2

R,38 37字节

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

感谢@ user5957401的额外字节!

测试用例:

> 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

我认为您可以使用文字if,else语句保存一个字节。即if(x>1)1+f(log(x))else 0短一个字节。
user5957401

2

R,34个字节

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

在线尝试!

一种非递归方法是可能的:36个字节,并从stdin获取输入。

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

2

Java 7,47字节

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

在线尝试。

上面的递归Java 7样式方法比迭代Java 8样式lambda短2个字节:

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

在线尝试。

说明:

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

使用Java 8 lambda可能会使它更短。
mbomb007 '16

@ mbomb007三年后回复,哈哈..(当时我只是在Java 7中进行代码搜索),但仍然要回答您的问题:不,不幸的是,Java 8 lambda比递归方法长2个字节。我已经将其添加到答案中,并且还添加了解释。
凯文·克鲁伊森

因此,您不能执行递归lambda?
mbomb007

@ mbomb007不,不幸的是,在Java中不是。在Python,JavaScript和我认为C#.NET以及递归lambda表达式是可能的,但在Java不是出于某种原因..
凯文Cruijssen

1

Emacs Lisp,38个字节

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

测试用例:

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

1

果冻,8 字节

-Ælß$Ị?‘

定义的简单实现。在线尝试!验证所有测试用例

怎么运行的

-Æ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个字节

非常简单,需要-M5.016(免费)启用__SUB__关键字以进行匿名递归。

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

另一种选择是

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

它是34个字节,并且对于所有输入> 1,都提供相同的输出,但是对于输入<= 1,返回特殊的false值。False在数值上等于零,但是打印为“”(空字符串),因此它可能不会没有资格。


好答案。你可以通过做赢1个字节sub{($_=pop)>1?1+__SUB__->(log):0},虽然
达达

1

CJam(16字节)

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

在线演示

带前提条件的简单while循环。(我在这里真正想要的是一种Golfscript样式的展开操作,但是CJam没有一个操作,并且GolfScript中的浮点是凌乱的,而不是一点儿高尔夫球)。


顺便说一句,这是我的第80个数学答案,并且今天为我赢得了第二个标记徽章。
彼得·泰勒


1

球拍,61字节

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

1

枫树,32,30 29字节

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

测试用例:

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

1

R,36个字节

与Plannapus略有不同

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

使用权限分配来运行代码-因此所需的数字必须位于代码之前。即

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

0

Mathematica,29个字节

简直像地狱一样简单,适用于可笑的大型以及负输入:

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

在此处输入图片说明



0

Perl 6,21个字节

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

在线尝试!

带括号的表达式是一个序列。 $_函数的参数是第一个元素。 *.log通过获取前一个元素的日志来生成每个后续元素。序列继续进行,直到结束条件1 >= *成立:1大于或等于当前元素。从序列中减去1会将其强制为一个数字:其长度。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.