Максимальная глубина рекурсии [закрыто]

15

Ваш язык имеет максимальную глубину рекурсии (MRD)?

Допустим, у вашего языка MRD = 500

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

Для приведенного выше случая ваша программа (или функция) должна вывести 500

Код-Гольф Самый короткий ответ побеждает!


источник
3
@cairdcoinheringaahing ... "который находит глубину рекурсии" означает, что
6
Я думаю, что основная проблема в этой задаче состоит в том, что печать жестко закодированного значения недопустима, но чтение жестко закодированной системной переменной - это нормально. Эти два не кажутся мне существенно разными.
DJMcMayhem
2
Встроенные модули @DJMcMayhem часто используют жестко закодированную информацию. Эта задача позволяет встроенные модули.
7
Да, это моя точка зрения. Они оба просто читают жестко запрограммированное значение, но одно разрешено, а другое нет.
DJMcMayhem
3
@DJMcMayhem, встроенный в mathematica, также может иметь швейцарский флаг (я видел этот вызов здесь), но размещение того же флага, что и jpg, недопустимо.

Ответы:

49

Mathematica, 15 байт

$RecursionLimit

¯ \ _ (ツ) _ / ¯

Попробуйте онлайн!

J42161217
источник
17
Конечно Mathematica имеет встроенный для этого! +1
Caird Coneheringaahing
1
Должен любить Mathematica +1
JungHwan Мин
Emacs Lisp в том же духе (19): max-lisp-eval-глубина
Caterpillar
19

Python 3 , 40 байт

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

Попробуйте онлайн!

Не просто читая это из встроенного. Мы начинаем с 2, а не с 1, потому что предложение исключение запускается на один уровень до ошибок. Конечно, это меньше на байт в Python 2.

FryAmTheEggman
источник
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){}`))())


Порт Japt , 24 байта

Не стоит публиковать это как отдельное решение, поскольку оно, по сути, идентично.

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

Проверь это


объяснение

Сам по себе JavaScript не имеет предела рекурсии как такового, скорее, ограничение накладывается интерпретатором (то есть браузером) - хорошо, что мы определяем языки их интерпретатором здесь! Среди прочих факторов, предел может варьироваться в зависимости от браузера и доступной памяти, на который влияют выполняемые операции. Следующий фрагмент иллюстрирует этот последний момент, используя 5 различных версий этого решения, которые я прошел. Как видно из последних 2 тестов, в 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вызывая ее, когда она не работает:

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!
Захари
3
33 байта:f=_=>eval('try{-~f()}catch(e){}')
Нейл,
@Neil: Я видел твою 34-байтовую версию, когда ложился спать, и пнул себя за то, что не думал об этом. Эта 33-байтовая версия вдохновлена. Благодарю.
Лохматый
13

Mathematica (без встроенного), 20 байтов

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

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

(Это фрагмент кода, который оценивает результат. Однако есть и другое решение Mathematica)

user202729
источник
10

J, 8 байт

1+$: ::]

Попробуйте онлайн!

Итак, я не знаю, как выполнить глагол без какого-либо ввода, и после небольшого поиска (а также личной интуиции) кажется, что это невозможно. Если это так, пожалуйста, дайте мне знать, как это сделать, и я либо удалю, либо обновлю свой ответ. Хотя на самом деле не имеет смысла давать глаголу никакой информации. В свете этого, данная функция ожидает 0, по умолчанию «пустой» ввод для целых чисел. Я, вероятно, могу изменить его, чтобы использовать пустой массив (0$0 ), если вы считаете, что это более подходящим.

Редактировать: OP позволил функции принимать 0.

объяснение

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

Это вызывает себя рекурсивно, добавляя 1 к входу (ожидаемый 0), пока он не достигнет ошибки стека. Когда он ошибается, он вызывает неблагоприятное (] -правильную идентичность) на входе, которая просто 0.

Кстати, место необходимо .

капуста
источник
1
выводит 6000 на мою машину. я думаю, что это должна быть честная игра, но вы всегда можете просто ответить(1+$: ::]) 0
Иона
@ Джона, честно говоря, я привык передавать функции. На моей машине это 6666 как ни странно.
Коул
6660 на iPad Pro. Здорово!
Аганью
То, как он обрабатывает максимальную глубину рекурсии, зависит от версии - на моем телефоне я получаю 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 да, я могу, спасибо!
сентября 17
Я получаю сообщение об ошибке (по крайней мере, на
Shaggy
@ Шагам, вам придется поменять местами строки для первой, после чего начнется импорт, чтобы дать встроенному имени возможность присвоить имя. Я обновлю ссылку.
Caird Coneheringaahing
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.

Конечно, максимальная глубина рекурсии в C зависит от множества факторов. В типичной 64-битной системе Linux размер стека по умолчанию составляет 8 МБ, а выравнивание стека - 16 байтов, поэтому вы получаете глубину рекурсии около 512 КБ для простых функций.

Также обратите внимание, что вышеприведенная программа не работает -O2из-за оптимизации хвостового вызова.

nwellnhof
источник
1
+1! Вы можете сохранить 4 байта, увеличивая cи вызывая exitи sigactionкак параметры. Это не вносит заметной разницы в результат: ссылка
TIO
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.

Попробуйте онлайн!

Giuseppe
источник
1
Вы можете сохранить семь байтов, удалив ressionsиз-за частичного совпадения с $.
Свен Хоэнштайн
1
Больше на будущее, чем в качестве вклада; согласие, что вам нужно обернуть это в cat ()? R выдаст что-то в большинстве случаев, так есть ли где-нибудь пост, разъясняющий хорошую практику / логику для подражания?
Преступно-
@SvenHohenstein черт, я всегда забываю об этом после того, как я написал R-код в хорошем стиле ... Спасибо!
Джузеппе
1
@CriminallyVulgar, например, увидеть этот пост в мета; в этом есть определенная неопределенность.
Джузеппе
4

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

2 байта удалены благодаря предложению Sanchises

@max_recursion_depth

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

Попробуйте онлайн!

Луис Мендо
источник
Вам не нужно (), так как max_recursion_depthэто также функция.
Sanchises
@ Рассылки Спасибо! Вы правы: даже если документ говорит, что это переменная, на самом деле это функция
Луис Мендо,
Ваше редактирование превратило это в дубликат другого ответа Octave, поэтому я сохранил его, @чтобы сохранить его отличным (определяя функцию, а не REPL'ing результат).
Sanchises
@Sanchises На самом деле я просто изменил это, хотя по другой причине (код должен фактически определять функцию)
Luis Mendo
Да, другой ответ больше похож на программу; Я не уверен, нужно ли это на самом деле disp(я бы включил это, но это мое личное мнение о Octave REPL, и я не уверен в каком-либо мета-консенсусе по этому
поводу
3

зш, 24 байта

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

Попробуйте онлайн! (См. Под отладкой)

Баш, 24 байта

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

Попробуйте онлайн! (См. Под отладкой)

ksh93, 27 байт

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

Попробуйте онлайн! (См. Под отладкой)

тире, 27 байт

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

Попробуйте онлайн! (Превышает выходные данные отладки tio, запустите его в своей собственной оболочке)

Тор
источник
1
Должны ли i=0и echoне быть включены в ваш счетчик байтов?
Лохматый
@Shaggy: Возможно, я изменил его на более автономное решение
Thor
1

Луа , 52 байта

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

Попробуйте онлайн!

Ataco
источник
@ В этом случае Шэгги да, потому что я использую имя f. Если бы это не было рекурсивным, я мог бы избежать этого
ATaco
Ах, я не заметил в fин pcall.
Лохматый
почему ваша программа останавливается на 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

Объяснение:

Попробуйте повторить, увеличьте x на единицу каждый раз, если ошибка, верните x.

{@[.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

Луа , 45 37 байт

x=2
f=load"x=x+1;f()"pcall(f)print(x)

Попробуйте онлайн!

Я не знаю, какое значение инициализировать, так xкак я не знаю, сколько существует промежуточных вызовов ...

Фелипе Нарди Батиста
источник
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, увеличивая счетчик на каждого рекурса. Когда он брошен, значение счетчика печатается.

Carcigenicate
источник
Вы можете сохранить 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

Если я могу запустить его, как ответ J выше, это будет 7 байт, потому что вы можете удалить последний yZ.

Попробуйте это онлайн здесь .

Maltysen
источник
5
Это не работает для меня. В автономном режиме я получаю ошибку сегментации. В сети я не получаю вывод вообще. Вы не можете поймать segfault.
Исаак
@isaacg подожди, это действительно странно. В Интернете это редко дает 764, но вы правы, большую часть времени это не дает результата.
Maltysen
0

Рубин, 39 байт

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

Подавление сообщения об ошибке немного короче, чем его спасение, так как по умолчанию rescue не ловит SystemStackError.

Есть более приятный ответ, если я могу вывести в унарном виде, представляющий n с n последовательных символов новой строки:

Рубин, 35 байт

$stderr=$<
f=->{puts;$.+=1;f[]}
f[]
histocrat
источник
0

Желе , 18 байт

:( *

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

Попробуйте онлайн!

Как?

* Насколько мне известно, Jelly:
(1) устанавливает предел рекурсии Python до установки большей части своего собственного интерпретатора и синтаксического анализа кода для запуска; и
(2) не может перехватывать ошибки Python.
Я не уверен, существует ли способ либо надежно оценить предел рекурсии, либо распечатать его при его обнаружении, кроме как фактически спросить Python, какое значение было установлено ( Хотелось бы посмотреть, можно ли это сделать, хотя!) Вот что делает код здесь:

“¡ż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
Джонатан Аллан
источник