Maksymalna głębokość rekurencji [zamknięte]

15

Czy twój język ma maksymalną głębokość rekurencji (MRD)?

Powiedzmy, że twój język ma MRD = 500

Napisz kod, który znajdzie głębokość rekurencji i wyświetli dokładną wartość

W powyższym przypadku twój program (lub funkcja) powinien wypisać 500

Code-Golf Najkrótsza odpowiedź wygrywa!


źródło
3
@cairdcoinheringaahing ... „który stwierdza głębokość rekurencji” oznacza, że ​​kodowanie jest nieprawidłowe
6
Myślę, że głównym problemem związanym z tym wyzwaniem jest to, że wydrukowanie wartości zakodowanej na stałe jest niedozwolone, ale odczytanie zakodowanej zmiennej systemowej jest w porządku. Te dwie rzeczy nie wydają mi się znacząco różne.
James
2
Wbudowane @DJMcMayhem wiele razy używają zakodowanych informacji. To wyzwanie pozwala na wbudowanie.
7
Tak, o to mi chodzi. Oboje po prostu czytają na stałe wartość, ale jedna jest dozwolona, ​​a druga nie.
James
3
@DJMcMayhem wbudowany w matematykę może mieć również flagę szwajcarską (widziałem to wyzwanie tutaj), ale opublikowanie tej samej flagi, co jpg, jest nieprawidłowe.

Odpowiedzi:

49

Mathematica, 15 bajtów

$RecursionLimit

¯ \ _ (ツ) _ / ¯

Wypróbuj online!

J42161217
źródło
17
Oczywiście Mathematica ma do tego wbudowaną funkcję! +1
caird coinheringaahing
1
Uwielbiam Mathematica +1
JungHwan Min
Emacs Lisp w tym samym stylu (19): max-lisp-eval-depth
Caterpillar
19

Python 3 , 40 bajtów

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

Wypróbuj online!

Bez czytania tylko z wbudowanego. Zaczynamy od 2 zamiast 1, ponieważ klauzula wyjątku jest uruchamiana jeden poziom, zanim wystąpi błąd. Jest to oczywiście bajt krótszy w pythonie 2.

FryAmTheEggman
źródło
1
Nie potrzebujesz 3 bajtów, aby zadzwonić do f
8bitwide
@ 8-bitowe zgłoszenia jako funkcja są domyślnie akceptowane. O ile pytanie konkretnie ich nie zakazuje, możesz przesłać funkcję wielokrotnego użytku jako rozwiązanie. Zauważysz, że wiele innych odpowiedzi na to pytanie robi to samo.
FryAmTheEggman
15

JavaScript (Babel) , 35 33 29 bajtów

f=_=>do{try{-~f()}catch(e){}}
  • 2 bajty zapisane dzięki Neilowi.

Wypróbuj tutaj lub użyj Snippet poniżej, aby go przetestować evalzamiast do.

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


Port Japt , 24 bajty

Naprawdę nie warto umieszczać tego jako osobnego rozwiązania, ponieważ jest to w zasadzie identyczne.

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

Sprawdź to


Wyjaśnienie

Sam JavaScript nie ma limitu rekurencji jako takiego, raczej jest narzucony przez tłumacza (tj. Przeglądarkę) - dobrze, że definiujemy języki przez ich tłumacza tutaj! Między innymi limit może się różnić w zależności od przeglądarki i dostępnej pamięci, na co mają wpływ wykonywane operacje. Poniższy fragment kodu ilustruje ten ostatni punkt, używając 5 różnych wersji tego rozwiązania, przez które przeszedłem. Jak widać z ostatnich 2 testów, w Chrome przynajmniej kolejność operacji może mieć znaczenie.

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}`))())

Biorąc to pod uwagę, dlatego nie mamy dogodności stałej lub metody do pracy. Zamiast tego stworzymy funkcję, która wywołuje się ciągle, zanim w końcu się wyłączy. W najprostszej formie to:

f=_=>f()

Ale to nie przydaje się nam w tym wyzwaniu, ponieważ generuje tylko błąd przepełnienia bez wskazania, ile razy się fnazywa. Możemy uniknąć błędu przez trying, aby dzwonić fciągle i catching, gdy się nie powiedzie:

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

Bez błędu, ale wciąż brak wartości zwracanej ile razy funkcja zdołała się wywołać przed niepowodzeniem, ponieważ catchtak naprawdę nic nie robi. Spróbujmy ocenić try / catchstwierdzenie:

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

Teraz zwracamy wartość (a ponieważ jest to golf golfowy, zaoszczędziliśmy kilka bajtów na faktycznym użyciu return). Zwracana jest jednak wartość undefined, ponieważ catchnic nie robi. Na szczęście dla nas -~undefined==1i -~n==n+1dlatego, wysyłając -~przed wezwaniem do f, w zasadzie dostaliśmy -~-~ ... -~-~undefined, z innym -~poprzedzającym każde połączenie, podając liczbę wywołań f.

f=_=>eval(`try{-~f()}catch(e){}`)
Kudłaty
źródło
Ładne rozwiązanie, ponieważ zakładam, że nie masz dostępu do głębokości rekurencji wbudowanej w JS!
Zacharý
3
33 bajty:f=_=>eval('try{-~f()}catch(e){}')
Neil
@ Neil: Widziałem twoją 34-bajtową wersję, kiedy szedłem spać, i kopnąłem się za to, że o tym nie pomyślałem. Ta 33-bajtowa wersja jest inspirowana. Dzięki.
Shaggy
13

Mathematica (bez wbudowanego), 20 bajtów

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

Pominięcie ;obliczy 1+$IterationLimit(prawdopodobnie dlatego, że Mathematica optymalizuje ogon funkcji). Alternatywnie 0 //. x_ -> x + 1oblicz ReplaceRepeatedwartość domyślną MaxIteration, czyli 65536(która jest większa niż obie powyższe wartości).

(Jest to fragment kodu, który ocenia wynik. Jednak inne rozwiązanie Mathematica również jest)

użytkownik202729
źródło
10

J, 8 bajtów

1+$: ::]

Wypróbuj online!

Tak więc, tak naprawdę nie wiem, jak wykonać czasownik bez wkładu, a krótkie wyszukiwanie (a także osobista intuicja) sprawia, że ​​wydaje się to niemożliwe. Jeśli tak, daj mi znać, jak to zrobić, a ja usunę lub zaktualizuję swoją odpowiedź. Jednak nie ma sensu, aby czasownikowi nie podawano żadnych danych wejściowych. W świetle tego, podana funkcja oczekuje 0, domyślnego „pustego” wejścia dla liczb całkowitych. Prawdopodobnie mogę to zmienić, aby użyć pustej tablicy (0$0 ), jeśli uważasz, że to bardziej pasuje.

Edycja: PO zezwolił tej funkcji na przyjęcie 0.

Wyjaśnienie

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

To wywołuje się rekurencyjnie, dodając 1 do wejścia (oczekiwane 0), aż napotka błąd stosu. Gdy ]popełni błąd, wywołuje na wejściu wartość ujemną ( -prawą tożsamość), która wynosi tylko 0.

Nawiasem mówiąc, przestrzeń jest niezbędna .

kapusta
źródło
1
wyświetla 6000 na mojej maszynie. fwiw myślę, że to powinna być uczciwa gra, ale zawsze możesz po prostu udzielić odpowiedzi(1+$: ::]) 0
Jonah
@Jonah fair point, jestem przyzwyczajony do przesyłania funkcji. Na mojej maszynie jest to 6666 dość dziwne.
cole
6660 na iPadzie pro. Chłodny!
Aganju
Sposób, w jaki obsługuje maksymalną głębokość rekurencji, wydaje się zależny od wersji - na moim telefonie otrzymuję 5999 (który wydaje się być wyłączony o 1). Na moim iPadzie (szczerze mówiąc nie pamiętam, który model) po prostu się zawiesza.
cole
9

Python 3 , 41 32 bajty

import sys
sys.getrecursionlimit

Wypróbuj online!

Zaoszczędź 9 bajtów dzięki @FryAmTheEggman!

34 bajty

from sys import*
getrecursionlimit

35 bajtów

__import__('sys').getrecursionlimit

Ostatnie 2 są dzięki @totallyhuman

Cairney Coheringaahing
źródło
32 bajty , 34 bajty i 35 bajtów . Wybierz swój. : P
całkowicie ludzki,
@FryAmTheEggman tak, mogę, dziękuję!
caird coinheringaahing
Dostaję błąd (przynajmniej w TIO), gdy próbuję uruchomić pierwsze 2.
Shaggy
@Shaggy będziesz musiał zamienić linie na pierwszy, import następuje po, aby umożliwić wbudowanemu przypisanie nazwy. Zaktualizuję link.
caird coinheringaahing
8

C (gcc, Linux x64), 180 133 bajtów

-4 bajty dzięki @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)));}

Wypróbuj online!

Instaluje moduł obsługi SIGSEGV (sygnał 11) z alternatywnym stosem sygnałów (minimalny rozmiar MINSIGSTKSZto 2 KB, flaga SA_ONSTACKto 0x08000000), a następnie wywołuje funkcję bez argumentów i rekurencyjnych zmiennych lokalnych, dopóki stos się nie przepełni. Interesujące jest to, że maksymalna głębokość rekurencji zmienia się w zależności od serii, prawdopodobnie z powodu ASLR.

Oczywiście maksymalna głębokość rekurencji w C zależy od wielu czynników. W typowym 64-bitowym systemie Linux domyślny rozmiar stosu wynosi 8 MB, a wyrównanie stosu to 16 bajtów, dzięki czemu głębokość rekurencji wynosi około 512 KB dla prostych funkcji.

Pamiętaj również, że powyższy program nie działa -O2 powodu optymalizacji wywołania ogona.

nwellnhof
źródło
1
+1! Możesz zapisać 4 bajty, zwiększając ci wywołując exitoraz sigactionjako parametry. Nie robi to zauważalnej różnicy w wyniku: link TIO
scottinet
6

Java 8, 131 51 48 47 43 bajtów

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

-80 bajtów dzięki @Nevay . Próbowałem też metody zamiast programu, ale popełniłem błąd, więc otrzymałem pełny program. Teraz jest to metoda.
-3 bajty dzięki @Neil dzięki wykorzystaniu finallyzamiast catch(Error e).
-5 bajtów dzięki @Nevay ponownie.

Wyjaśnienie:

Wypróbuj tutaj.

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
Kevin Cruijssen
źródło
1
51 bajtów:int c(){try{return-~c();}catch(Error e){return 1;}}
Nevay
2
@Nevay Często zamieszczasz doskonałe odpowiedzi w komentarzach. Możesz opublikować je jako odpowiedzi i zdobyć reputację. Nic nie zabrania zadawania pytań przez kilka odpowiedzi w języku Java. ;-)
Olivier Grégoire,
2
int c(){int n=1;try{n=-~c();}finally{return n;}}oszczędza 3 bajty, ale daje inną odpowiedź?
Neil
2
47 bajtów:int c(){int n=1;try{n+=c();}finally{return n;}}
Nevay
1
43 bajty:int d;int c(){try{c();}finally{return++d;}}
Nevay
4

Oktawa, 19 bajtów

max_recursion_depth

Stosowanie:

octave:1> max_recursion_depth
ans =  256
Ilya
źródło
4

R , 32 26 18 bajtów

-8 bajtów dzięki Svenowi Hohensteinowi : $częściowe dopasowanie, więc możemy po prostu użyć expzamiast pełnego expressions.

cat(options()$exp)

optionsKomenda może być również używany do ustawiania głębokości rekurencji, to znaczy,options(expressions=500) za 500.

Wypróbuj online!

Giuseppe
źródło
1
Możesz zapisać siedem bajtów, usuwając z ressionspowodu częściowego dopasowania z $.
Sven Hohenstein,
1
Więcej do wykorzystania w przyszłości niż jako wkład; czy istnieje konsensus, który należy zawinąć w cat ()? R wyda coś w większości przypadków, więc czy jest gdzieś post wyjaśniający dobre praktyki / logikę do naśladowania?
CriminallyVulgar
@ SvenHohenstein dang, zawsze o tym zapominam po tym, jak napisam kod R w dobrym stylu ... Dziękuję!
Giuseppe,
1
@CriminallyVulgar zobacz na przykład ten post w meta; z pewnością jest w tym trochę niepewności.
Giuseppe,
4

Oktawa , 25 22 20 bajtów

Usunięto 2 bajty dzięki sugestii Sanchises

@max_recursion_depth

Anonimowa funkcja generująca wartość.

Wypróbuj online!

Luis Mendo
źródło
Nie potrzebujesz (), ponieważ max_recursion_depthjest to również funkcja.
Sanchises
@Sanchises Thanks! Masz rację: nawet jeśli dokument mówi, że jest to zmienna, w rzeczywistości jest to funkcja
Luis Mendo
Twoja edycja zmieniła to w duplikat drugiej odpowiedzi Octave, dlatego @postanowiłem zachować jej odrębność (definiowanie funkcji zamiast REPL'owania wyniku).
Sanchises
@ Sanchises Właściwie właśnie to zmieniłem, chociaż z innego powodu (kod powinien faktycznie definiować funkcję)
Luis Mendo
Tak, druga odpowiedź jest bardziej jak program; Nie jestem pewien, czy to rzeczywiście wymagałoby disp(ja bym to
załączył
3

zsh, 24 bajty

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

Wypróbuj online! (Patrz pod debugowaniem)

bash, 24 bajty

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

Wypróbuj online!(Patrz pod debugowaniem)

ksh93, 27 bajtów

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

Wypróbuj online!(Patrz pod debugowaniem)

myślnik, 27 bajtów

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

Wypróbuj online! (Przekracza wyjście debugowania tio, uruchom je we własnej powłoce)

Thor
źródło
1
Powinny i=0i echonie mogą być uwzględnione w liczbie bajtów?
Shaggy
@Shaggy: Być może zmieniłem to na bardziej samodzielne rozwiązanie
Thor
1

Lua , 52 bajty

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

Wypróbuj online!

ATaco
źródło
@ Shaggy w tym przypadku tak, ponieważ używam nazwy f. Gdyby to nie było rekurencyjne, nie mogłem tego zrobić
ATaco
Ach, ja nie dostrzec fin pcall.
Shaggy
dlaczego twój program zatrzymuje się na 200? tutaj widać, że w tej prostej funkcji wykracza ona poza 200. jeśli ją usuniesz --, możesz potwierdzić, że jest to połączenie rekurencyjne bez optymalizacji
Felipe Nardi Batista
1

q / kdb +, 16 bajtów

Rozwiązanie:

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

Przykład:

/ 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

Wyjaśnienie:

Spróbuj powtórzyć, zwiększ x za każdym razem, jeśli błąd, zwróć 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
streetster
źródło
1

Excel-VBA, 26 bajtów

?Application.MaxIterations

Nie sama głębokość rekurencji, w rzeczywistości wyświetla maksymalną liczbę iteracji dla komórki w arkuszu programu Excel. Biorąc pod uwagę, że dane wyjściowe dotyczą języka innego niż język, w którym jest napisany, być może jest to bardziej odpowiednie:

Excel + Excel-Vba, 3 + 38 = 41 bajtów

Function f:f=Application.MaxIterations

Jak to można wywołać z komórki za pomocą

=f(

W przypadku VBA bez wbudowanego:

Excel-VBA, 53 44 40 bajtów

-9, ponieważ zmienna nie musi już być inicjowana ani drukowana

-4, ponieważ wykonywanie kodu nie musi być zakończone, aby uniknąć wielu wydruków

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

Wywołaj za pomocą sz w bezpośrednim oknie, wyprowadza do komórki A1 arkusza

(uruchomienie ostrzeżenia zajmuje teraz chwilę, dodaj Application.ScreenUpdating = Falsenajpierw)

Greedo
źródło
1

Lua , 45 37 bajtów

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

Wypróbuj online!

I don't know which value to initialize x with as I don't know the number of intermediary calls there are...

Felipe Nardi Batista
źródło
1

Clojure, 72 55 48 bytes

-23 bytes by getting rid of the atom

-7 bytes thanks to @madstap. Switched to using fn over def and #(), and pr over println.

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

Wrote and tested on my phone. The Clojure REPL app gave me a depth of 13087.

Basic solution. Recurse until a SO is thrown, incrementing a counter each recurse. When it's thrown, the value of the counter is printed.

Carcigenicate
źródło
You can save 5 bytes by using pr instead of println. Also -2 bytes by making the fn like this: ((fn f[x](,,,))0) instead of (def f #(,,,))(f 0).
madstap
@madstap Thanks. I'll make the changes in a bit.
Carcigenicate
1

VBA, any type, 41 39 bytes

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

Call using ?A() in the Immediate window, or as worksheet function.

Note: Returns 4613 in Excel-VBA, while the answer by @Greedo returns 3666 on my system (highest should be the max). Apparently also varies between Office programs (Access-VBA returns 4622, Word-VBA 4615)

Edit: Guess VBA auto-adds parantheses, so removed them.

Erik A
źródło
0

Pyth - 9 bytes

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.

Maltysen
źródło
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

Forth, 48 bytes

Loops until it hits the limit.

: m 1+ recurse ;
: f 0 ['] m catch drop ; f .

Try it online

mbomb007
źródło
0

Tcl, 49 bytes

proc R {i\ 1} {if [catch {R [incr i]}] {puts $i}}

Try it online!

sergiol
źródło
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[]
histocrat
źródło
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
Jonathan Allan
źródło