超対数を計算する


29

これは簡単な課題です。

数を考えるとn >= 0、出力超対数(またはログ*、ログスターを、または対数を繰り返し、同等であるため、nこのような課題に対して負になることはありません。)のn

log *(n):= {n <= 1の場合は0;  1 + log *(log(n))if n> 1}

これは、テトラションに対する2つの逆関数の1つです。もう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


回答:


14

ゼリー、8 バイト

ÆlÐĿĊḊi1

オンラインでお試しください!または、すべてのテストケースを確認します

バックグラウンド

結果が変化しなくなるまで、入力の自然対数と後続の結果を連続して取得することから始めます。これが機能するのは、自然対数の複素平面への拡張には固定小数点があるためです。if z = e -W(-1) ≈0.318 + 1.337i –ここで、WランバートW関数を示しますlog(z)= zです。

入力nの場合[n、log(n)、log(log(n))、…、z]を計算した後、まず各結果にシーリング関数を適用します。Jellyの実装(Ċ)は実際に複素数の虚数部を代わりに計算します、とにかくこれらには興味がありません。

のk 番目のアプリケーションログは以下の値が得られるか、に等しい1Ċ戻ります1を初めて。その最初の1の0から始まるインデックスが望ましい結果です。

単純な実装(計算1ベースのインデックス、デクリメント)は、エッジケース0のために失敗しますこれは、対数のリストに1がありません。実際、入力0の場合、対数のシーケンスは

[0, None]

これは、Jellyの対数(Æl)が過負荷になっているためです。最初にmath.log(実際の対数)を試み、次にcmath.log(複素数の対数)を試み、最後に「あきらめて」を返しますNone。幸いなことに、Ċ同様にオーバーロードされ、切り上げまたは虚数部を取得できない場合は、単に引数を返します。

同様に、入力1は戻ります

[1, 0, None]

それはかかわらない他のアプローチで問題を作成するかもしれませんĊ

この問題を解決する1つの方法は、対数の配列に適用(デキュー、最初の要素を削除)です。この地図

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

したがって、どちらのリストにも1はありません。この方法では、最初の1のインデックスを見つけると、0(見つからない)が返されます。これは、入力0および1の望ましい出力です。

使い方

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

これは、ゼリーの中で明白でない方法で過負荷になっている3つの原子の1つです。




7

Javascript、45 27 26バイト

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

テストスイート(3 rev)

条件付きで1バイトを保存してから関数をラムダに変換してくれた@LeakyNunに感謝し、falseを指摘した@Neilは<= 1の戻り値で問題ありません(テストを==ではなく==に変更)


私はes6なしでそれをやっていたが、ええ、それは1バイト短くなります、ありがとう。
–CShark

なぜラムダを使用しないのですか?
リーキー修道女

それは私の最初の本能はありませんので、何の正当な理由は、私はちょうど、その多くのそれを使用していないしていない
CShark

どうやらfalse(整数式で自動的に0に変換されるため)0の代わりに返すことが許可されているようです|0。その場合、をドロップできます。
ニール

それは1バイトを節約しますが、「0に自動変換する」とはどういう意味ですか?それは何ですか"?
–CShark

6

Mathematica、21バイト

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

再帰的な匿名関数。整数を入力として受け取り、そのスーパー対数を出力として返します。指定された定義を使用するだけです。


3
実際に、事前にビルトインがあるかどうかを確認しました。なかったときは驚きました。:D
mbomb007



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== 0Pythonにある)を返します。


はい、Falseに使用できます0
mbomb007

また、あなたは(andではなくを使用してif else)私の素朴な実装を破りました。グラッツ。
mbomb007

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

3

J21 19 18 16バイト

Leaky Nunに2バイト、Galen Ivanovに1バイト、FrownyFrogに2バイトを保存しました!

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

オンラインでお試しください!

テストケース

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

私の18バイトのソリューションは次のとおりです2#@}.^.^:(0<])^:a:(この問題の重複であることが判明したものを解決し 始めました。)
ガレンイワノフ

2#@}.(0>.^.)^:a:動作するようです。
-FrownyFrog

しかし、それが同等かどうかはわかりません。
-FrownyFrog


2

MATLAB /オクターブ、44バイト

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

すべてを1つの匿名関数として実行しようとしましたが、MATLAB / Octaveがブールfalse(ゼロ)値で乗算された場合でも式を評価し続けることを忘れていました。

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


はい、短絡製品があるといいでしょう:-)
ルイスメンドー

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ステートメントを使用して、1バイトを保存できると思います。つまりif(x>1)1+f(log(x))else 0、1バイト短くなります。
-user5957401


2

Java 7、47バイト

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

オンラインでお試しください。

上記の再帰的なJava 7スタイルのメソッドは、反復的なJava 8スタイルのラムダよりも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ラムダを使用すると、短くなる場合があります。
mbomb007

@ mbomb007は3年後に応答します(笑)(当時はJava 7でコードゴルフをしていました)が、あなたの質問に答えるために:いいえ、残念ながらJava 8ラムダは再帰的メソッドより2バイト長くなっています。回答に追加し、説明も追加しました。
ケビンクルーッセン

だから、再帰的なラムダを行うことはできませんか?
mbomb007

@ mbomb007いいえ、残念ながらJavaではそうではありません。Pythonのは、JavaScriptでは、私はC#.NETを考えるだけでなく、再帰的なラムダは可能ですが、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

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は数値的にゼロに等しいが、 ""(空の文字列)資格がありません。


素晴らしい答え。sub{($_=pop)>1?1+__SUB__->(log):0}ただし、そうすることで1バイト獲得できます
ダダ

1

CJam(16バイト)

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

オンラインデモ

前提条件を使用した単純なwhileループ。(ここで本当に欲しいのは、Golfscriptスタイルの展開操作ですが、CJamにはありません。GolfScriptの浮動小数点は乱雑で、まったくゴルフではありません)。


余談ですが、これは数学での私の80番目の回答であり、今日2番目のタグバッジを獲得しました。
ピーターテイラー



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 >= *がtrueになるまで続きます。1は現在の要素以上です。シーケンスから1を引くと、強制的に数値に変換されます:その長さ。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.