Maximale Rekursionstiefe [geschlossen]

15

Hat Ihre Sprache eine maximale Rekursionstiefe (MRD)?

Angenommen, Ihre Sprache hat MRD = 500

Schreiben Sie einen Code, der die Rekursionstiefe ermittelt und den genauen Wert ausgibt

Für den obigen Fall sollte Ihr Programm (oder Ihre Funktion) 500 ausgeben

Code-Golf Kürzeste Antwort gewinnt!


quelle
3
@cairdcoinheringaahing ... "das die Rekursionstiefe findet" bedeutet, dass die Hardcodierung ungültig ist
6
Ich denke, das Hauptproblem bei dieser Herausforderung besteht darin, dass das Drucken eines fest codierten Werts nicht zulässig ist, das Lesen einer fest codierten Systemvariablen jedoch in Ordnung ist. Die beiden scheinen sich für mich nicht wesentlich zu unterscheiden.
DJMcMayhem
2
Die in @DJMcMayhem integrierten Funktionen verwenden häufig fest codierte Informationen. Diese Herausforderung ermöglicht integrierte Funktionen.
7
Ja, das ist mein Punkt. Sie lesen beide einfach einen fest codierten Wert, aber einer ist erlaubt und der andere nicht.
DJMcMayhem
3
@DJMcMayhem, das in Mathematica integriert ist, kann auch die Schweizer Flagge haben (ich habe diese Herausforderung hier gesehen), aber das Posten der gleichen Flagge wie jpg ist ungültig.

Antworten:

49

Mathematica, 15 Bytes

$RecursionLimit

¯ \ _ (ツ) _ / ¯

Probieren Sie es online!

J42161217
quelle
17
Natürlich hat Mathematica dafür einen eingebaut! +1
Caird Coinheringaahing
1
Muss ich
Emacs Lisp in der gleichen Richtung (19): Max-Lisp-Eval-Tiefe
Caterpillar
19

Python 3 , 40 Bytes

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

Probieren Sie es online!

Ohne es nur aus dem eingebauten zu lesen. Wir beginnen bei 2 statt bei 1, da die except-Klausel eine Ebene ausgeführt wird, bevor sie fehlerhaft ist. Dies ist natürlich ein Byte kürzer in Python 2.

FryAmTheEggman
quelle
1
Benötigen
@ 8bitwide-Einreichungen als Funktion werden standardmäßig akzeptiert. Sofern die Frage sie nicht ausdrücklich verbietet, können Sie eine wiederverwendbare Funktion als Lösung einreichen. Sie werden feststellen, dass viele andere Antworten auf diese Frage dasselbe tun.
FryAmTheEggman
15

JavaScript (Babel) , 35 33 29 Bytes

f=_=>do{try{-~f()}catch(e){}}
  • 2 Bytes gespart dank Neil.

Versuchen Sie es hier , oder verwenden Sie das Snippet unten zu testen es mit evalstatt do.

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


Japt Port, 24 Byte

Es lohnt sich nicht, dies als separate Lösung zu veröffentlichen, da es im Wesentlichen identisch ist.

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

Probier es aus


Erläuterung

JavaScript selbst hat kein Rekursionslimit an sich, sondern das Limit wird vom Interpreter (dh dem Browser) auferlegt - gut, dass wir hier die Sprachen durch den Interpreter definieren! Unter anderem kann das Limit je nach Browser und verfügbarem Speicher variieren, was sich auf die ausgeführten Vorgänge auswirkt. Das folgende Snippet veranschaulicht diesen letzten Punkt anhand der 5 verschiedenen Versionen dieser Lösung, die ich durchlaufen habe. Wie Sie den letzten beiden Tests entnehmen können, kann zumindest in Chrome die Reihenfolge der Vorgänge einen Unterschied ausmachen.

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

Aus diesem Grund verfügen wir nicht über die Bequemlichkeit einer Konstante oder Methode, mit der wir arbeiten können. Stattdessen werden wir eine Funktion erstellen, die sich ständig selbst aufruft, bevor sie schließlich ausfällt. In seiner einfachsten Form ist das:

f=_=>f()

Aber das nützt uns nicht viel für diese Herausforderung, da es nur einen Überlauffehler auslöst, ohne dass angegeben wird, wie oft es sich fselbst angerufen hat. Wir können den Fehler vermeiden , indem trying zu Anruf fkontinuierlich und catching , wenn es fehlschlägt:

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

Kein Fehler, aber immer noch kein Rückgabewert dafür, wie oft die Funktion es geschafft hat, sich selbst aufzurufen, bevor ein Fehler auftrat, da sie catcheigentlich nichts unternimmt. Lassen Sie uns versuchen, die try / catchAnweisung zu bewerten :

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

Jetzt wird ein Wert zurückgegeben (und da dies Codegolf ist, haben wir uns mit einem tatsächlichen Wert ein paar Bytes gespart return). Der zurückgegebene Wert ist jedoch wieder, undefinedweil der catchkeine Aktion ausführt. Zum Glück für uns -~undefined==1und -~n==n+1so durch ein Aufspringen -~vor dem Aufruf fhaben wir im Wesentlichen bekommen -~-~ ... -~-~undefined, mit einem anderen -~bei jedem Aufruf vorangestellt, so dass die Anzahl der Zeiten fgenannt wurden.

f=_=>eval(`try{-~f()}catch(e){}`)
Zottelig
quelle
Gute Lösung, da ich davon ausgehe, dass Sie keinen Zugriff auf eine in JS integrierte Rekursionstiefe haben!
Zacharý
3
33 Bytes:f=_=>eval('try{-~f()}catch(e){}')
Neil
@Neil: Ich habe deine 34-Byte-Version gesehen, als ich ins Bett ging, und mich selbst getreten, weil ich nicht daran gedacht habe. Diese 33-Byte-Version ist inspiriert. Vielen Dank.
Shaggy
13

Mathematica (nicht integriert), 20 Byte

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

Das Weglassen der ;Berechnung wird 1+$IterationLimit(wahrscheinlich, weil Mathematica die Funktion schwanzoptimiert ). Alternativ können Sie auch die Standardeinstellung 0 //. x_ -> x + 1berechnen , d. H.ReplaceRepeatedMaxIteration65536 (die größer ist als sowohl Wert ist oben).

(Dies ist ein Code-Snippet, das als Ergebnis ausgewertet wird. Die andere Mathematica-Lösung ist es jedoch auch.)

user202729
quelle
10

J, 8 Bytes

1+$: ::]

Probieren Sie es online!

Ich weiß also nicht, wie man ein Verb ohne Eingabe ausführt, und eine kurze Suche (sowie eine persönliche Intuition) lässt es so scheinen, als wäre das nicht möglich. Wenn ja, lassen Sie es mich bitte wissen und ich werde meine Antwort entweder löschen oder aktualisieren. Es ist jedoch nicht sinnvoll, einem Verb keine Eingabe zu geben. In Anbetracht dessen erwartet die angegebene Funktion 0die Standardeingabe "leer" für Ganzzahlen. Ich kann es wahrscheinlich ändern, um das leere Array zu verwenden (0$0 ) zu verwenden, wenn Sie denken, dass das angemessener ist.

Edit: Das OP hat der Funktion erlaubt, 0 zu nehmen.

Erläuterung

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

Dies ruft sich selbst rekursiv auf und addiert 1 zur Eingabe (0 wird erwartet), bis ein Stack-Fehler auftritt. Bei Fehlern wird die negative ( ]-right identity) für die Eingabe aufgerufen, die nur 0 ist.

Der Platz ist übrigens notwendig .

cole
quelle
1
gibt 6000 auf meinem Rechner aus. Ich denke, dies sollte ein faires Spiel sein, aber Sie können immer nur Ihre Antwort geben(1+$: ::]) 0
Jonah
@Jonah fair point, ich bin es gewohnt, Funktionen einzureichen. Auf meinem Rechner ist es merkwürdigerweise 6666.
Cole
6660 auf einem iPad Pro. Cool!
Aganju
Die Art und Weise, wie mit der maximalen Rekursionstiefe umgegangen wird, scheint versionsabhängig zu sein - auf meinem Telefon erhalte ich 5999 (was um 1 abgeschaltet zu sein scheint). Auf meinem iPad (ehrlich gesagt, ich weiß nicht mehr, welches Modell) stürzt es einfach ab.
Cole
9

Python 3 , 41 32 Bytes

import sys
sys.getrecursionlimit

Probieren Sie es online!

9 Bytes gespart dank @FryAmTheEggman!

34 Bytes

from sys import*
getrecursionlimit

35 Bytes

__import__('sys').getrecursionlimit

Die letzten beiden sind @totallyhuman zu verdanken

Caird Coinheringaahing
quelle
32 Bytes , 34 Bytes und 35 Bytes . Treffen Sie Ihre Wahl. : P
totalhuman
@FryAmTheEggman ja ich kann, danke!
Caird Coinheringaahing
Ich erhalte eine Fehlermeldung (zumindest bei TIO), wenn ich versuche, die ersten 2 auszuführen.
Shaggy
@Shaggy Sie müssen die Zeilen für die erste tauschen, der Import erfolgt danach, damit dem eingebauten einen Namen zugewiesen werden kann. Ich werde den Link aktualisieren.
Caird Coinheringaahing
8

C (gcc, Linux x64), 180 133 Bytes

-4 Bytes dank @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)));}

Probieren Sie es online!

Installiert einen SIGSEGV-Handler (Signal 11) mit einem alternativen Signalstapel (Mindestgröße MINSIGSTKSZ2 KB, Flag SA_ONSTACK0x08000000) und ruft dann eine Funktion ohne Argumente und ohne lokale Variablen rekursiv auf, bis der Stapel überläuft. Es ist interessant, dass die maximale Rekursionstiefe über Läufe variiert, wahrscheinlich aufgrund von ASLR.

Die maximale Rekursionstiefe in C hängt natürlich von vielen Faktoren ab. Auf einem typischen 64-Bit-Linux-System beträgt die Standard-Stack-Größe 8 MB und die Stack-Ausrichtung 16 Byte, sodass Sie für einfache Funktionen eine Rekursionstiefe von ca. 512 KB erhalten.

Beachten Sie auch, dass das obige Programm -O2aufgrund der Tail Call-Optimierung nicht funktioniert .

nwellnhof
quelle
1
+1! Sie können 4 Bytes durch Inkrementieren cund Aufrufen von exitund sigactionals Parameter sparen . Das macht keinen nennenswerten Unterschied für das Ergebnis: TIO Link
Scottinet
6

Java 8, 131 51 48 47 43 Bytes

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

-80 Bytes dank @Nevay . Ich habe auch eine Methode anstelle eines Programms ausprobiert, habe aber einen Fehler gemacht und bin zu einem vollständigen Programm gekommen. Jetzt ist es eine Methode.
-3 Bytes dank @Neil unter Verwendung von finallyanstelle von catch(Error e).
-5 byte danke nochmal an @Nevay .

Erläuterung:

Probieren Sie es hier aus.

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
quelle
1
51 Bytes:int c(){try{return-~c();}catch(Error e){return 1;}}
Nevay
2
@Nevay Du postest oft exzellente Antworten in Kommentaren. Sie könnten sie als Antworten posten und sich einen guten Ruf verschaffen. Nichts verbietet es einer Frage, mehrere Java-Antworten zu haben. ;-)
Olivier Grégoire
2
int c(){int n=1;try{n=-~c();}finally{return n;}}Speichert 3 Bytes, gibt mir aber eine andere Antwort?
Neil
2
47 Bytes:int c(){int n=1;try{n+=c();}finally{return n;}}
Nevay
1
43 Bytes:int d;int c(){try{c();}finally{return++d;}}
Nevay
4

Oktave, 19 Bytes

max_recursion_depth

Verwendung:

octave:1> max_recursion_depth
ans =  256
Ilya
quelle
4

R , 32 26 18 Bytes

-8 Bytes danke an Sven Hohenstein : $wird partiell abgleichen, also können wir einfach expanstelle des vollen verwenden expressions.

cat(options()$exp)

Der optionsBefehl kann auch verwendet werden, um die Rekursionstiefe festzulegen, dh options(expressions=500)für 500.

Probieren Sie es online!

Giuseppe
quelle
1
Sie können sieben Bytes einsparen, indem Sie ressionsaufgrund einer teilweisen Übereinstimmung mit entfernen $.
Sven Hohenstein
1
Mehr zum Nachschlagen als als Beitrag; ist der Konsens, dass Sie dies in cat () einwickeln müssen? R ausgeben wird etwas in den meisten Fällen, so gibt es eine Post irgendwo Klärung gute Praxis / Logik zu folgen?
CriminallyVulgar
@SvenHohenstein dang, das vergesse ich immer, nachdem ich R-Code in gutem Stil geschrieben habe ... Danke!
Giuseppe
1
@ CriminallyVulgar siehe zum Beispiel diesen Beitrag in Meta; es gibt sicherlich eine gewisse Unsicherheit darüber.
Giuseppe
4

Oktave , 25 22 20 Bytes

2 Bytes entfernt dank eines Vorschlags von Sanchises

@max_recursion_depth

Anonyme Funktion, die den Wert ausgibt.

Probieren Sie es online!

Luis Mendo
quelle
Sie brauchen das nicht (), da max_recursion_depthes auch eine Funktion ist.
Sanchises
@Sanchises Danke! Sie haben Recht: Auch wenn der Arzt sagt, dass es sich um eine Variable handelt, handelt es sich tatsächlich um eine Funktion
Luis Mendo
Ihre Bearbeitung hat dies in ein Duplikat der anderen Octave-Antwort umgewandelt, weshalb ich es beibehalten habe @, um es eindeutig zu halten (indem ich eine Funktion definiere, anstatt das Ergebnis zu ERSETZEN).
Sanchises
@Sanchises Eigentlich habe ich das nur aus einem anderen Grund geändert (der Code sollte eigentlich eine Funktion definieren)
Luis Mendo
Ja, die andere Antwort ist eher ein Programm. Ich bin mir nicht sicher, ob dies tatsächlich erforderlich sein sollte disp(ich hätte es aufgenommen, aber das ist meine persönliche Meinung zu Octave REPL, und ich bin mir nicht sicher, ob dies ein
Metakonsens ist
3

zsh, 24 bytes

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

Probieren Sie es online! (Siehe unter Debug)

Bash, 24 Bytes

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

Probieren Sie es online! (Siehe unter Debug)

ksh93, 27 bytes

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

Probieren Sie es online! (Siehe unter Debug)

Strich, 27 Bytes

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

Probieren Sie es online! (Übersteigt die Ausgabe von tio debug, führen Sie es in Ihrer eigenen Shell aus)

Thor
quelle
1
Sollten i=0und echonicht in Ihrer Byteanzahl enthalten sein?
Shaggy
@ Shaggy: Vielleicht habe ich es zu einer in sich geschlossenen Lösung geändert
Thor
1

Lua , 52 Bytes

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

Probieren Sie es online!

Ein Taco
quelle
@Shaggy in diesem Fall ja, weil ich den Namen f benutze. Wenn dies nicht rekursiv wäre, könnte ich damit durchkommen, es nicht zu haben
ATaco
Ah, ich habe vor Ort nicht fin pcall.
Shaggy
Warum stoppt Ihr Programm bei 200? hier können Sie sehen, dass in dieser einfachen Funktion die 200 überschritten wird. Wenn Sie die entfernen --, können Sie bestätigen, dass es sich immer noch um einen rekursiven Aufruf ohne Optimierungen handelt
Felipe Nardi Batista,
1

q / kdb +, 16 Bytes

Lösung:

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

Beispiel:

/ 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

Erläuterung:

Versuchen Sie, x jedes Mal um eins zu erhöhen. Wenn ein Fehler auftritt, geben Sie x zurück.

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

Excel-VBA, 26 Bytes

?Application.MaxIterations

Hierbei wird nicht die Rekursionstiefe per se ausgegeben, sondern die maximale Anzahl von Iterationen für eine Zelle in einem Excel-Arbeitsblatt. Da sich die Ausgabe auf eine andere Sprache als die Sprache bezieht, in der dies geschrieben ist, ist dies möglicherweise angemessener:

Excel + Excel-Vba, 3 + 38 = 41 Bytes

Function f:f=Application.MaxIterations

Wie das aus einer Zelle mit aufgerufen werden kann

=f(

Für VBA ohne eingebautes:

Excel-VBA, 53 44 40 Bytes

-9 als Variable muss nicht mehr initialisiert oder gedruckt werden

-4, da die Codeausführung nicht mehr beendet werden muss, um Mehrfachdrucke zu vermeiden

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

Rufen Sie mit s im direkten Fenster auf und geben Sie es in Zelle A1 des Arbeitsblatts aus

(Warnung dauert eine Weile, bis sie ausgeführt wird. Application.ScreenUpdating = FalseZuerst hinzufügen. )

Greedo
quelle
1

Lua , 45 37 Bytes

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

Probieren Sie es online!

Ich weiß nicht, mit welchem ​​Wert xich initialisieren soll, da ich nicht weiß, wie viele Zwischenrufe es gibt ...

Felipe Nardi Batista
quelle
1

Clojure, 72 55 48 Bytes

-23 Bytes durch Entfernen des Atoms

-7 Bytes dank @madstap. Umgestellt auf die Verwendung von fnover defund #()und prover println.

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

Schrieb und testete auf meinem Handy. Die Clojure REPL App gab mir eine Tiefe von 13087.

Grundlösung. Rekursieren Sie, bis ein SO ausgelöst wird, und erhöhen Sie bei jeder Rekursion einen Zähler. Wenn es geworfen wird, wird der Wert des Zählers gedruckt.

Karzigenat
quelle
Sie können 5 Bytes sparen, indem Sie pranstelle von verwenden println. Auch -2 Bytes, indem Sie die Fn wie folgt machen: ((fn f[x](,,,))0)statt (def f #(,,,))(f 0).
Madstap
@madstap Danke. Ich werde die Änderungen gleich vornehmen.
Carcigenicate
1

VBA, beliebiger Typ, 41 bis 39 Byte

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

Rufen Sie über ?A()das Direktfenster oder als Arbeitsblattfunktion auf.

Hinweis: Gibt in Excel-VBA 4613 zurück, während die Antwort von @Greedo auf meinem System 3666 zurückgibt (der höchste Wert sollte der Höchstwert sein). Offenbar variiert auch zwischen Office-Programmen (Access-VBA gibt 4622, Word-VBA 4615 zurück)

Bearbeiten: Vermutlich fügt VBA automatisch Klammern hinzu, entfernt sie also.

Erik A
quelle
0

Pyth - 9 Bytes

L.xyhbbyZ

Wenn ich es wie die J Antwort oben laufen lassen kann, ist dieses 7 Bytes, weil Sie das letzte herausnehmen können yZ.

Probieren Sie es hier online aus .

Maltysen
quelle
5
Das funktioniert bei mir nicht. Offline erhalte ich einen Segmentierungsfehler. Online bekomme ich überhaupt keine Ausgabe. Sie können einen Segfault nicht fangen.
Isaacg
@isaacg warte das ist wirklich komisch. Online gibt es selten 764, aber Sie haben die meiste Zeit Recht, es gibt keine Ausgabe.
Maltysen
0

Viertens 48 Bytes

Schleifen, bis das Limit erreicht ist.

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

Probieren Sie es online aus

mbomb007
quelle
0

Ruby, 39 Bytes

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

Das Unterdrücken der Fehlermeldung ist etwas kürzer als das Wiederherstellen, da sie standardmäßig rescuenicht abfängtSystemStackError .

Es gibt eine käsigere Antwort, wenn ich unärgerlich ausgeben kann und nn aufeinanderfolgende Zeilenumbrüche darstelle:

Ruby, 35 Bytes

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

Gelee , 18 Bytes

:( *

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

Probieren Sie es online!

Wie?

* Soweit mir bekannt ist, seit Jelly:
(1) legt das Python-Rekursionslimit fest, bevor ein Großteil seines eigenen Interpreters eingerichtet und der auszuführende Code analysiert wird; und
(2) kann Python-Fehler
nicht abfangen. Ich bin mir nicht sicher, ob es eine Möglichkeit gibt, das Rekursionslimit entweder zuverlässig auszuwerten oder auszudrucken, wenn es entdeckt wird. Ich würde gerne sehen, ob das möglich ist!) So sieht der Code hier aus:

“¡ż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
quelle