Максимальна глибина рекурсії [закрита]


15

Чи має ваша мова максимальну глибину рекурсії (MRD)?

Скажімо, ваша мова має MRD = 500

Напишіть код, який знаходить глибину рекурсії та виводить точне значення

У випадку, вказаному вище, ваша програма (або функція) повинна виводити 500

Код-гольф Найкоротша відповідь виграє!


3
@cairdcoinheringaahing ... "що знаходить глибину рекурсії" означає, що

6
Я думаю, що головна проблема цього завдання полягає в тому, що друкувати твердо кодовані значення не дозволяється, але читання твердокодированной системної змінної - це добре. Вони насправді не здаються суттєво різними для мене.
Джеймс

2
Вбудовані @DJMcMayhem багато разів використовують жорстко кодовану інформацію. Цей виклик дозволяє вбудовувати модулі.

7
Так, це моя суть. Вони обидва просто читають твердо кодовані значення, але одне дозволено, а інше - ні.
Джеймс

3
@DJMcMayhem вбудований в математику також може мати швейцарський прапор (я бачив цю проблему тут), але розміщення того ж прапора, що й jpg, недійсне.

Відповіді:



19

Python 3 , 40 байт

def f(x=2):
 try:f(x+1)
 except:print(x)

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

Не читаючи його лише з вбудованого. Ми починаємо з 2, а не з 1, оскільки за винятком пункту запускається один рівень, перш ніж він помиляється. Це, звичайно, байт коротший у python 2.


1
Вам не потрібно 3 байти, щоб зателефонувати в f
8bitwide

@ 8-бітні подання як функція приймаються за замовчуванням. Якщо питання спеціально не забороняє їх, ви можете подати функцію багаторазового використання як рішення. Ви помітите, що багато інших відповідей на це питання роблять те саме.
FryAmTheEggman

15

JavaScript (Babel) , 35 33 29 байт

f=_=>do{try{-~f()}catch(e){}}
  • 2 байти збережено завдяки Нілу.

Спробуйте тут , або скористайтеся фрагментом нижче, щоб перевірити його evalзамість do.

console.log((f=_=>eval(`try{-~f()}catch(e){}`))())


Порт- джапт , 24 байти

Насправді не варто розміщувати це як окреме рішення, оскільки воно, по суті, ідентичне.

Ox`try\{-~rp()}¯t®(e)\{}

Перевірте це


Пояснення

Сам JavaScript сам по собі не має межі рекурсії, скоріше обмеження накладається перекладачем (тобто браузером) - добре, що ми визначаємо мови, використовуючи їх перекладач. Серед інших факторів, ліміт може змінюватись залежно від браузера та наявної пам'яті, на що впливають виконувані операції. Наступний фрагмент ілюструє цю останню точку, використовуючи 5 різних версій цього рішення, які я пройшов. Як видно з двох останніх тестів, у Chrome, принаймні, навіть порядок операцій може змінити значення.

console.log((f=(i=0)=>eval(`try{f(i+1)}catch(e){i}`))())
console.log((f=i=>eval(`try{f(-~i)}catch(e){i}`))())
console.log((f=(i=0)=>eval(`try{f(++i)}catch(e){i}`))())
console.log((f=_=>eval(`try{-~f()}catch(e){}`))())
console.log((f=_=>eval(`try{f()+1}catch(e){0}`))())
console.log((f=_=>eval(`try{1+f()}catch(e){0}`))())

Враховуючи це, ми не маємо зручності константи або методу роботи. Натомість ми будемо створювати функцію, яка постійно дзвонить перед тим, зрештою, вискакуючи. У найпростішій формі це:

f=_=>f()

Але це не дуже корисно нам для цього виклику, оскільки воно лише видаляє помилку переповнення, не вказуючи на те, скільки разів fназиває себе. Ми можемо уникнути помилок при tryІНГАХ дзвонити fбезперервно іcatch ING , коли він зазнає невдачі:

f=_=>{try{f()}catch(e){}}

Ніякої помилки, але все-таки немає значення повернення, скільки разів функція встигла зателефонувати собі, перш ніж вийти з ладу, оскільки catchнасправді нічого не робить. Спробуємо оцінитиtry / catch твердження:

f=_=>eval(`try{f()}catch(e){}`)

Тепер ми отримали значення, яке повертається (і, оскільки це код гольфу, ми заощадили кілька байтів за допомогою фактичного return). Значення, яке повертається, undefinedзнову ж таки, тому що catchне робить нічого. На щастя для нас, -~undefined==1і -~n==n+1так, вискочивши -~перед дзвінком f, ми, по суті, отримали -~-~ ... -~-~undefinedще один -~заздалегідь приздалегідь кожен виклик, який дав нам кількість разів f.

f=_=>eval(`try{-~f()}catch(e){}`)

Гарне рішення, оскільки я припускаю, що у вас немає доступу до глибини рекурсії, вбудованої в JS!
Zacharý

3
33 байти:f=_=>eval('try{-~f()}catch(e){}')
Ніл

@Neil: Я бачив вашу 34-байтну версію, коли я лягав спати, і брикався, що не думав про це. Ця 33-байтна версія натхненна. Спасибі.
Shaggy

13

Математика (без вбудованого), 20 байт

#0[#+1];&@1
%[[1,1]]

Опускаючи ;волю, буде обчислено 1+$IterationLimit(можливо, тому, що Mathematica хвіст оптимізує функцію). Альтернативно 0 //. x_ -> x + 1обчисліть ReplaceRepeatedза замовчуванням MaxIteration, тобто 65536(що більше, ніж обидва значення вище).

(Це фрагмент коду, який оцінює результат. Однак інше рішення Mathematica також є)


10

J, 8 байт

1+$: ::]

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

Отже, я насправді не знаю, як виконати дієслово без будь-якого введення, а за допомогою короткого пошуку (а також особистої інтуїції) здається, що це неможливо. Якщо це так, будь ласка, дайте мені знати, як це зробити, і я або видалю або оновлю відповідь. Однак це не має сенсу для дієслова, який не має введення. З огляду на це, очікувана функція очікується 0, типовий "порожній" вхід для цілих чисел. Можливо, я можу змінити його для використання порожнього масиву (0$0 ), якщо ви вважаєте, що це більше подобається.

Редагувати: ОП дозволило функції приймати 0.

Пояснення

1+$: ::]
     ::]  Assign adverse: if an error occurs, call ] (the identify function)
1+        Add one to
  $:      Recursive call to self

Це викликає себе рекурсивно, додаючи 1 на вхід (0 очікуваних), поки не виявиться помилка стека. Коли він помиляється, він викликає негативний ( ]-right ідентичність) на вході, який становить всього 0.

До речі, простір необхідний .


1
виводить 6000 на мою машину. fwiw, я думаю, це повинна бути чесна гра, але завжди можна просто відповісти(1+$: ::]) 0
Jonah

@ Joona fair point, я звик подавати функції. На моїй машині це 6666 як не дивно.
коул

6660 на iPad pro. Класно!
серпня 1717 року

Те, як вона справляється з максимальною глибиною рекурсії, виглядає залежно від версії - на своєму телефоні я отримую 5999 (що, здається, вимкнуто на 1). На моєму iPad (чесно не пам’ятаю, яка модель) він просто виходить з ладу.
коул

9

Python 3 , 41 32 байт

import sys
sys.getrecursionlimit

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

Збережено 9 байт завдяки @FryAmTheEggman!

34 байти

from sys import*
getrecursionlimit

35 байт

__import__('sys').getrecursionlimit

Останні 2 - завдяки @totallyhuman


32 байти , 34 байти та 35 байт . Візьміть свій вибір. : P
повністюлюдський

@FryAmTheEggman так, можу, дякую!
caird coinheringaahing

Я отримую помилку (принаймні, на TIO), коли намагаюся запустити перший 2.
Shaggy

@Shaggy Вам доведеться поміняти рядки на перший, імпорт продовжується, щоб дозволити вбудованому призначити ім'я. Я поновлю посилання.
caird coinheringaahing

8

C (gcc, Linux x64), 180 133 байт

-4 байти завдяки @scottinet

c;f(){f(++c);}h(){exit(printf("%d",c));}main(){int b[512];f(sigaction(11,(int*[]){h,[17]=1<<27},sigaltstack((int*[]){b,0,2048},0)));}

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

Встановлює обробник SIGSEGV (сигнал 11) з альтернативним стеком сигналу (мінімальний розмір MINSIGSTKSZ- 2 Кб, прапорSA_ONSTACK - 0x08000000), потім викликає функцію без аргументів і не існує локальних змінних рекурсивно, поки стек не переповнений. Цікаво, що максимальна глибина рекурсії змінюється в різних пробігах, ймовірно, завдяки ASLR.

Максимальна глибина рекурсії в С, звичайно, залежить від безлічі факторів. Для типової 64-розрядної системи Linux розмір стека за замовчуванням становить 8 Мб, а вирівнювання стека - 16 байт, тому ви отримуєте глибину рекурсії близько 512 К для простих функцій.

Також зауважте, що програма вище не працює -O2через оптимізацію хвостових викликів.


1
+1! Ви можете зберегти 4 байти шляхом збільшення cта виклику exitта sigactionяк параметри. Це не помітно
змінить

6

Java 8, 131 51 48 47 43 байт

int d;int c(){try{c();}finally{return++d;}}

-80 байт завдяки @Nevay . Я також спробував метод замість програми, але помилився, і закінчився повною програмою. Тепер це метод.
-3 байти завдяки @Neil , використовуючи finallyзамість цього catch(Error e).
-5 байт знову завдяки @Nevay

Пояснення:

Спробуйте тут.

int d;                 // Depth-integer `d` on class-level (implicit 0)
int c(){               // Method without parameter and integer return-type
  try{c();}            //  Recursive call
  finally{return++d;}  //  Increase depth-integer `d` and always return it,
                       //   whether a StackOverflowError occurs or not
}                      // End of method

1
51 байт:int c(){try{return-~c();}catch(Error e){return 1;}}
Невай

2
@Nevay Ви часто залишаєте відмінні відповіді в коментарях. Ви можете опублікувати їх як відповіді та отримати репутацію. Ніщо не забороняє жодного запитання мати декілька відповідей на Java. ;-)
Олів'є Грегоар

2
int c(){int n=1;try{n=-~c();}finally{return n;}}економить 3 байти, але дає мені іншу відповідь?
Ніл

2
47 байт:int c(){int n=1;try{n+=c();}finally{return n;}}
Невай

1
43 байти:int d;int c(){try{c();}finally{return++d;}}
Невай

4

Октава, 19 байт

max_recursion_depth

Використання:

octave:1> max_recursion_depth
ans =  256

4

R , 32 26 18 байт

-8 байт завдяки Свена Гогенштейна : $буде часткове узгодження, тому ми можемо просто використовувати expзамість повного expressions.

cat(options()$exp)

optionsКоманда також може бути використана для установки глибини рекурсії, тобто options(expressions=500)за 500.

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


1
Ви можете зберегти сім байтів, видаливши ressionsчерез часткове узгодження з $.
Свен Хогенштайн

1
Більше для подальших довідок, ніж як внесок; чи існує думка про те, що вам потрібно загорнути це у cat ()? R видасть щось у більшості обставин, тож чи є десь повідомлення, де роз'яснюється добра практика / логіка, яку слід дотримуватися?
Кримінально-

@SvenHohenstein, я завжди забуваю про це після того, як пишу R-код у хорошому стилі ... Дякую!
Джузеппе

1
@CriminallyVulgar див., Наприклад, цю публікацію в мета; у цьому, безумовно, є певна невизначеність.
Джузеппе

4

Октава , 25 22 20 байт

2 байти вилучено завдяки пропозиції Санчісе

@max_recursion_depth

Анонімна функція, яка виводить значення.

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


Вам не потрібен (), як max_recursion_depthце також функція.
Санчіз

@Sanchises Дякую! Ви маєте рацію: навіть якщо доктор каже, що це змінна, це насправді функція
Луїс Мендо

Ваша редакція перетворила це в дублікат іншої відповіді Октави, отже, я зберіг, @щоб він відрізнявся (визначаючи функцію, а не ЗАПОВІДАючи результат).
Санчіз

@Sanchises Насправді я просто змінив це, хоча з іншої причини (код насправді повинен визначати функцію)
Луїс Мендо

Так, інша відповідь більше схожа на програму; Я не впевнений, чи потрібно це насправді вимагати disp(я б це включив, але це моя особиста думка щодо Octave REPL, і я не впевнений у мета-консенсусі з цього приводу)
Sanchises

3

zsh, 24 байт

f(){f $[++i];f};set -x;f

Спробуйте в Інтернеті! (Дивіться під налагодженням)

баш, 24 байти

f(){ f $[++i];};set -x;f

Спробуйте в Інтернеті! (Дивіться під налагодженням)

кш93, 27 байт

f(){ f $(($1+1));};set -x;f

Спробуйте в Інтернеті! (Дивіться під налагодженням)

тире, 27 байт

f(){ f $(($1+1));};set -x;f

Спробуйте в Інтернеті! (Перевищує вихід налагодження tio, запустіть його у власній оболонці)


1
Якщо i=0і echoже не бути включені в підрахунку байт?
Shaggy

@Shaggy: Можливо, я змінив це на більш самодостатнє рішення
Тор

1

Луа , 52 байти

f=load"b,e=pcall(f,(...or 3)+1)return b and e or..."

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


@Shaggy в цьому випадку так, тому що я використовую ім'я f. Якби це не було рекурсивно, я міг би піти, не маючи цього
ATaco

Ах, я не помітив в fін pcall.
Shaggy

чому ваша програма зупиняється на 200? тут ви бачите, що в цій простій функції вона перевищує 200. Якщо ви вилучите, --ви можете підтвердити, що це все-таки рекурсивний дзвінок без оптимізацій
Феліпе Нарді Батіста,

1

q / kdb +, 16 байт

Рішення:

{@[.z.s;x+1;x]}0

Приклад:

/ solution
q){@[.z.s;x+1;x]}0
2000

/ without apply (try/catch)
q){.z.s x+1}0
'stack
@
{.z.s x+1}
2001

Пояснення:

Спробуйте повторити, збільшуйте х кожен раз на кожен раз, якщо помилка, поверніть х.

{@[.z.s;x+1;x]}0 / the solution
{             }0 / call lambda function with 0
 @[    ;   ; ]   / @[function;argument;catch]
   .z.s          / call self (ie recurse)
        x+1      / increment x
            x    / return x if function returns error

1

Excel-VBA, 26 байт

?Application.MaxIterations

Не глибина рекурсії як такої, це фактично виводить максимальну кількість ітерацій для комірки на робочому аркуші Excel. Враховуючи, що висновок стосується іншої мови, ніж мови, якою це написано, можливо, це є більш доречним:

Excel + Excel-Vba, 3 + 38 = 41 байт

Function f:f=Application.MaxIterations

Як це можна назвати з комірки с

=f(

Для VBA без вбудованого:

Excel-VBA, 53 44 40 байт

-9, оскільки змінну більше не потрібно ініціалізувати чи друкувати

-4, оскільки виконання коду більше не потрібно закінчувати, щоб уникнути декількох роздруківків

Sub s:[A1]=[A1]+1:On Error Resume Next:s

Виклик із s у прямому вікні, виводить на комірку A1 робочого аркуша

(попередження триває деякий час, додайте Application.ScreenUpdating = Falseспочатку)



1

Clojure, 72 55 48 байт

-23 байти шляхом позбавлення від атома

-7 байт завдяки @madstap. Переключено на використання fnнад defі над #(), і prзнову println.

((fn f[i](try(f(inc i))(catch Error e(pr i))))0)

Написав і перевірив на своєму телефоні. Додаток Clojure REPL дав мені глибину 13087.

Основне рішення. Рекурсуйте, поки не буде кинуто SO, збільшуючи лічильник кожен повтор. Коли вона кидається, друкується значення лічильника.


Ви можете зберегти 5 байт, використовуючи prзамість println. Також -2 байти, зробивши fn таким чином: ((fn f[x](,,,))0)замість (def f #(,,,))(f 0).
madstap

@madstap Дякую Я трохи внесу зміни.
Carcigenicate

1

VBA, будь-якого типу, 41 39 байт

Function A:On Error Resume Next:A=A()+1

Телефонуйте, використовуючи ?A()у вікні негайного пошуку або як функцію робочого аркуша.

Примітка: повертає 4613 в Excel-VBA, тоді як відповідь @Greedo повертає 3666 в моїй системі (найвищим має бути макс.). Мабуть, також варіюється між програмами Office (Access-VBA повертається 4622, Word-VBA 4615)

Редагувати: Вгадайте, VBA автоматично додає парантези, тому їх видалено.


0

Pyth - 9 байт

L.xyhbbyZ

If I can run it like the J answer above, this is 7 bytes because you can take out the last yZ.

Try it online here.


5
This doesn't work for me. Offline, I get a segmentation fault. Online, I get no output at all. You can't catch a segfault.
isaacg

@isaacg wait this is really weird. Online, it rarely gives 764, but you're right most of the time it gives no output.
Maltysen




0

Ruby, 39 bytes

END{p$.}
$stderr=$<
f=->{$.+=1;f[]}
f[]

Suppressing the error message is a little shorter than rescuing it, since by default rescue doesn't catch SystemStackError.

There's a cheesier answer if I can output in unary, representing n with n consecutive newline characters:

Ruby, 35 bytes

$stderr=$<
f=->{puts;$.+=1;f[]}
f[]

0

Jelly, 18 bytes

:( *

“¡żuẋ×HẒpƙ7"8!ƭ»ŒV

Try it online!

How?

* Since Jelly as far as I am aware:
(1) sets the Python recursion limit prior to setting up much of its own interpreter and parsing the code to be run; and
(2) has no way of catching Python errors
I'm not sure if there is a way to either reliably evaluate the recursion limit or to print it out as it is discovered other than to actually ask Python what the value was set to (I'd love to see if it can be done though!) so that's what the code here does:

“¡żuẋ×HẒpƙ7"8!ƭ»ŒV - Link: no arguments
“¡żuẋ×HẒpƙ7"8!ƭ»   - compression of "sys."+"get"+"recursion"+"limit"+"()"
                ŒV - evaluate as Python code
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.