Обчисліть супер-логарифм


29

Це має бути простим викликом.

Враховуючи число n >= 0, виведіть супер-логарифм (або log *, log-зірку або ітераційний логарифм , які є еквівалентними, оскільки nніколи не є негативним для цього виклику) n.

log * (n): = {0, якщо n <= 1;  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


Відповіді:


14

Желе , 8 байт

ÆlÐĿĊḊi1

Спробуйте в Інтернеті! або перевірити всі тестові випадки .

Фон

Почнемо з послідовного взяття природних логарифмів введення та подальших результатів, поки результат більше не зміниться. Це працює тому, що розширення природного логарифму до складної площини має фіксовану точку ; якщо z = e -W (-1) ≈ 0,318 + 1,333i - де W позначає функцію Ламберта W - маємо log (z) = z .

Для введення n , після обчислення [n, log (n), log (log (n)),…, z] , ми спочатку застосовуємо функцію стелі до кожного з результатів. Реалізація Jelly ( Ċ) насправді обчислює уявну частину складного числа замість , але нас це все одно не цікавить.

Як тільки k- е застосування журналу дасть значення менше або дорівнює 1 , Ċповерне 1 вперше. 0-індекс цього першого 1 є бажаним результатом.

Безпосередня реалізація (обчислювальний індекс, декремент) не вдається через крайній випадок 0 , який не має 1 у своєму списку логарифмів. Насправді для введення 0 послідовність логарифмів є

[0, None]

Це тому, що логарифм Джеллі ( Æl) перевантажений; він спочатку намагається math.log(справжній логарифм), потім cmath.log(складний логарифм) і, нарешті, "здається" і повертається None. На щастя, Ċаналогічно перевантажений і просто повертає його аргумент, якщо він не може зібрати або взяти уявну участь.

Так само повертається вхід 1

[1, 0, None]

які можуть створювати проблеми в інших підходах, які не стосуються або не передбачають Ċ.

Один із способів вирішити цю проблему - застосувати (dequeue; видаляє перший елемент) до масиву логарифмів. Це карти

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

Це один з єдиних трьох атомів в желе, які перевантажуються неочевидним чином.




7

Javascript, 45 27 26 байт

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

Ось тестовий набір (3-й об.)

Дякуємо @LeakyNun за збереження 1 байта з умовною, а потім перетворюючою функцією в лямбда, а @Neil за вказівку помилкової - це норма повернення для <= 1 (змінений тест на = = замість ===)


Я робив це без es6, але так, це було б на 1 байт коротше, дякую.
CShark

Чому б ви не вживали лямбда?
Leaky Nun

немає поважних причин, я просто не використовував його так багато, тому це не мій перший інстинкт
CShark

Мабуть, нам дозволяється повертатися falseзамість 0 (оскільки воно автоматично перетворюється на 0 у цілому виразі), у цьому випадку ви можете скинути це |0.
Ніл

Це дозволило б заощадити 1 байт, але що ви маєте на увазі під "він автоматично перетворюється на 0"? Що це"?
CShark

6

Математика, 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(що є == 0в Python).


Так, Falseможе бути використаний для 0.
mbomb007

Крім того, ви перемогли мою наївну реалізацію (використовуючи, andа не використовуючи if else). Грати.
mbomb007


3

MATL , 15 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

J , 21 19 18 16 байт

Збережено 2 байти для Leaky Nun, 1 байт для Галена Іванова, і 2 байти для FrownyFrog!

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

Спробував це зробити як одну анонімну функцію, але я забув, що MATLAB / Octave продовжує оцінювати вирази, навіть якщо вони помножені на булеві помилкові (нульові) значення:

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. тобто if(x>1)1+f(log(x))else 0на один байт коротше.
користувач5957401


2

Java 7, 47 байт

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

Спробуйте в Інтернеті.

Рекурсивний метод стилю Java 7, наведений вище, на 2 байти коротший, ніж ітеративна лямбда в стилі Java 8:

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 відповів через три роки, ха-ха .. (на той час я займався лише кодом-гольфінгу на Java 7), але все одно відповім на ваше запитання: ні, на жаль, лямбда Java 8 на 2 байти довше рекурсивного методу. Я додав це до своєї відповіді, а також додав пояснення.
Kevin Cruijssen

Отже, ви не можете робити рекурсивні лямбда?
mbomb007

@ mbomb007 Ні, в Java на жаль немає. У Python, JavaScript, і я думаю, що також C # .NET, можливі рекурсивні лямбдати, але на Java не чомусь ..
Кевін Круїйсен

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. Хибне числово дорівнює нулю, але друкується як "" (порожня рядок), тому, ймовірно, це не ' t не має права.


Чудова відповідь. Ви можете виграти 1 байт, зробивши sub{($_=pop)>1?1+__SUB__->(log):0}все-таки
Дада,

1

CJam (16 байт)

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

Демонстрація в Інтернеті

Простий цикл з попередньою умовою. (Мені дуже хочеться тут розгорнути операцію в стилі Golfscript, але у CJam цього немає, і плаваюча точка в GolfScript є безладною і зовсім не гофрованою).


Що стосується моєї, це моя 80-а відповідь з математики і отримала сьогодні мій другий значок тегу.
Пітер Тейлор



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

Математика, 29 байт

Просто, як і все пекло, і працює як для великих, так і для негативних входів:

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

enter image description here



0

Perl 6 , 21 байт

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

Спробуйте в Інтернеті!

Вираз у дужках - це послідовність. $_, аргумент функції - перший елемент. *.logгенерує кожен наступний елемент, приймаючи журнал попереднього елемента. Послідовність триває до тих пір, поки не закінчиться умова, що закінчується 1 >= *: 1 більший або рівний поточному елементу. Віднімання 1 з послідовності примушує його до числа: його довжина.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.