Kedalaman Rekursi Maksimal [ditutup]

15

Apakah bahasa Anda memiliki kedalaman rekursi maksimum (MRD)?

Katakanlah bahasa Anda memiliki MRD = 500

Tulis kode yang menemukan kedalaman rekursi dan menampilkan nilai yang tepat

Untuk kasus di atas, program Anda (atau fungsi) harus menghasilkan 500

Kode-Golf Jawaban terpendek menang!


sumber
3
@cairdcoinheringaahing ... "yang menemukan kedalaman rekursi" berarti hardcoding tidak valid
6
Saya pikir masalah utama dengan tantangan ini adalah bahwa mencetak nilai hardcoded tidak diperbolehkan, tetapi membaca variabel sistem hardcoded baik-baik saja. Keduanya tidak begitu berbeda bagi saya.
DJMcMayhem
2
@DJMcMayhem built-in berkali-kali menggunakan informasi hardcoded. Tantangan ini memungkinkan built-in.
7
Ya, itu maksud saya. Mereka berdua hanya membaca nilai hardcoded, tetapi satu diizinkan dan yang lainnya tidak.
DJMcMayhem
3
@DJMcMayhem bawaan di Mathematica juga dapat memiliki bendera swiss (saya telah melihat tantangan ini di sini), tetapi memposting bendera yang sama dengan jpg tidak valid.

Jawaban:

49

Mathematica, 15 byte

$RecursionLimit

¯ \ _ (ツ) _ / ¯

Cobalah online!

J42161217
sumber
17
Tentu saja Mathematica memiliki bawaan untuk ini! +1
caird coinheringaahing
1
Harus mencintai Mathematica +1
JungHwan Min
Emacs Lisp dalam nada yang sama (19): max-lisp-eval-depth
Caterpillar
19

Python 3 , 40 byte

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

Cobalah online!

Tanpa hanya membacanya dari builtin. Kita mulai dari 2 bukannya 1 karena klausa kecuali dijalankan satu tingkat sebelum kesalahan. Ini adalah byte yang lebih pendek di python 2, tentu saja.

FryAmTheEggman
sumber
1
Anda tidak perlu 3 byte untuk menelepon f
8bitwide
@ 8 bit pengiriman sebagai fungsi diterima secara default. Kecuali jika pertanyaan tersebut secara khusus melarang mereka, Anda dapat mengirimkan fungsi yang dapat digunakan kembali sebagai solusi. Anda akan melihat bahwa banyak jawaban lain pada pertanyaan ini melakukan hal yang sama.
FryAmTheEggman
15

JavaScript (Babel) , 35 33 29 byte

f=_=>do{try{-~f()}catch(e){}}
  • 2 byte disimpan berkat Neil.

Mencobanya di sini , atau gunakan Cuplikan di bawah ini untuk mengujinya dengan evalbukan do.

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


Port Japt , 24 byte

Tidak benar-benar layak memposting ini sebagai solusi terpisah karena pada dasarnya identik.

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

Menguji


Penjelasan

JavaScript itu sendiri tidak memiliki batas rekursi per se, melainkan batas yang dikenakan oleh penerjemah (yaitu, browser) - hal yang baik kita mendefinisikan bahasa berdasarkan babak penerjemah mereka di sini! Di antara faktor-faktor lain, batas dapat bervariasi berdasarkan browser dan memori yang tersedia, yang dipengaruhi oleh operasi yang dilakukan. Cuplikan berikut menggambarkan poin terakhir, menggunakan 5 versi berbeda dari solusi ini yang saya lalui. Seperti yang dapat Anda lihat dari 2 tes terakhir, di Chrome, setidaknya, bahkan urutan operasi dapat membuat perbedaan.

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

Oleh karena itu, kami tidak memiliki kenyamanan konstanta atau metode untuk bekerja dengannya. Sebagai gantinya, kita akan membuat fungsi yang memanggil dirinya sendiri secara terus-menerus sebelum, akhirnya, keluar. Dalam bentuknya yang paling sederhana yaitu:

f=_=>f()

Tapi itu tidak banyak berguna bagi kami untuk tantangan ini karena hanya melemparkan kesalahan meluap tanpa indikasi berapa kali fmenyebut dirinya. Kita bisa menghindari kesalahan dengan trying panggilan fterus menerus dan catching ketika gagal:

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

Tidak ada kesalahan, tetapi masih tidak ada nilai balik berapa kali fungsi berhasil memanggil dirinya sendiri sebelum gagal, karena catchsebenarnya tidak melakukan apa-apa. Mari kita coba mengevaluasi try / catchpernyataan:

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

Sekarang kita punya nilai yang dikembalikan (dan, karena ini adalah kode golf, menyelamatkan diri beberapa byte dari penggunaan yang sebenarnya return). Nilai yang dikembalikan adalah undefined, sekali lagi karena catchtidak melakukan apa-apa. Untungnya bagi kita -~undefined==1dan -~n==n+1, dengan muncul -~di depan panggilan untuk f, pada dasarnya kita punya -~-~ ... -~-~undefined, dengan yang lain -~diawali dengan setiap panggilan, memberi kita berapa kali fdipanggil.

f=_=>eval(`try{-~f()}catch(e){}`)
Shaggy
sumber
Solusi yang bagus, karena saya berasumsi Anda tidak memiliki akses ke kedalaman rekursi yang ada di JS!
Zacharý
3
33 byte:f=_=>eval('try{-~f()}catch(e){}')
Neil
@ Neil: Saya melihat versi 34 byte Anda ketika saya pergi tidur dan menendang diri saya karena tidak memikirkannya. Versi 33 byte itu terinspirasi. Terima kasih.
Shaggy
13

Mathematica (tidak ada built-in), 20 byte

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

Menghilangkan ;akan menghitung 1+$IterationLimit(mungkin karena Mathematica tail-mengoptimalkan fungsi). Alternatifnya, 0 //. x_ -> x + 1menghitung ReplaceRepeateddefault MaxIteration, yaitu 65536(yang lebih besar dari kedua nilai di atas).

(Ini adalah potongan kode yang mengevaluasi hasilnya. Namun solusi Mathematica lainnya juga)

pengguna202729
sumber
10

J, 8 byte

1+$: ::]

Cobalah online!

Jadi, saya tidak benar-benar tahu bagaimana mengeksekusi kata kerja tanpa input dan beberapa pencarian singkat (serta intuisi pribadi) membuatnya tampak seperti itu tidak mungkin. Jika ya, beri tahu saya cara melakukannya dan saya akan menghapus atau memperbarui jawaban saya. Namun tidak masuk akal jika kata kerja tidak diberi input. Sehubungan dengan ini, fungsi yang diberikan mengharapkan 0, input "kosong" default untuk bilangan bulat. Saya mungkin bisa mengubahnya untuk menggunakan array kosong (0$0 ) jika Anda pikir itu lebih cocok.

Sunting: OP telah memungkinkan fungsi untuk mengambil 0.

Penjelasan

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

Ini panggilan itu sendiri secara rekursif, menambahkan 1 ke input (0 diharapkan) hingga hits kesalahan tumpukan. Ketika kesalahan, itu memanggil yang merugikan ( ]identitas-kanan) pada input, yang hanya 0.

Ngomong-ngomong, ruang itu perlu .

cole
sumber
1
output 6000 pada mesin saya. fwiw saya pikir ini harus menjadi permainan yang adil, tetapi Anda selalu bisa membuat jawaban Anda(1+$: ::]) 0
Jonah
@Jonah fair point, saya sudah terbiasa mengirimkan fungsi. Di mesin saya, anehnya 6666.
cole
6660 pada pro iPad. Keren!
Aganju
Cara menangani kedalaman rekursi maksimum tampaknya bergantung pada versi - pada ponsel saya saya dapatkan 5999 (yang tampaknya dimatikan oleh 1). Di iPad saya (jujur ​​saya tidak ingat model mana), itu hanya crash.
cole
9

Python 3 , 41 32 byte

import sys
sys.getrecursionlimit

Cobalah online!

Disimpan 9 byte berkat @FryAmTheEggman!

34 byte

from sys import*
getrecursionlimit

35 byte

__import__('sys').getrecursionlimit

2 yang terakhir adalah terima kasih kepada @totallyhuman

caird coinheringaahing
sumber
32 byte , 34 byte dan 35 byte . Ambil pilihanmu. : P
totallyhuman
@FryAmTheEggman ya saya bisa, terima kasih!
caird coinheringaahing
Saya mendapatkan kesalahan (pada TIO, setidaknya) ketika mencoba menjalankan yang pertama 2.
Shaggy
@ Shaggy Anda harus menukar garis untuk yang pertama, impor berjalan untuk memungkinkan bawaan yang dialokasikan nama. Saya akan memperbarui tautannya.
caird coinheringaahing
8

C (gcc, Linux x64), 180 133 byte

-4 byte terima kasih kepada @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)));}

Cobalah online!

Menginstal handler SIGSEGV (sinyal 11) dengan tumpukan sinyal alternatif (ukuran minimum MINSIGSTKSZadalah 2 KB, flag SA_ONSTACK0x08000000), kemudian memanggil fungsi tanpa argumen dan tidak ada variabel lokal secara rekursif sampai stack meluap. Sangat menarik bahwa kedalaman rekursi maksimum bervariasi di seluruh lintasan, mungkin karena ASLR.

Kedalaman rekursi maksimum dalam C tergantung pada banyak faktor, tentu saja. Pada sistem Linux 64-bit yang tipikal, ukuran stack default adalah 8 MB, dan alignment stack adalah 16 byte, sehingga Anda mendapatkan kedalaman rekursi sekitar 512K untuk fungsi-fungsi sederhana.

Perhatikan juga bahwa program di atas tidak berfungsi -O2karena pengoptimalan panggilan ekor.

nwellnhof
sumber
1
+1! Anda dapat menyimpan 4 byte dengan menambah cdan memanggil exitdan sigactionsebagai parameter. Ini tidak membuat perbedaan nyata pada hasilnya: TIO link
scottinet
6

Java 8, 131 51 48 47 43 byte

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

-80 byte terima kasih kepada @Nevay . Saya mencoba metode bukan program juga, tetapi membuat kesalahan sehingga berakhir dengan program penuh .. Sekarang metode.
-3 byte terima kasih kepada @Neil dengan memanfaatkan finallybukannya catch(Error e).
-5 byte terima kasih kepada @Nevay lagi.

Penjelasan:

Coba di sini.

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
sumber
1
51 byte:int c(){try{return-~c();}catch(Error e){return 1;}}
Nevay
2
@Nevay Anda sering memposting jawaban luar biasa dalam komentar. Anda dapat mempostingnya sebagai jawaban, dan mendapatkan beberapa reputasi. Tidak ada yang melarang pertanyaan apa pun dari memiliki beberapa jawaban Java. ;-)
Olivier Grégoire
2
int c(){int n=1;try{n=-~c();}finally{return n;}}menghemat 3 byte tetapi memberi saya jawaban yang berbeda?
Neil
2
47 byte:int c(){int n=1;try{n+=c();}finally{return n;}}
Nevay
1
43 byte:int d;int c(){try{c();}finally{return++d;}}
Nevay
4

Oktaf, 19 byte

max_recursion_depth

Pemakaian:

octave:1> max_recursion_depth
ans =  256
Ilya
sumber
4

R, 32 26 18 bytes

-8 bytes thanks to Sven Hohenstein : $ will do partial matching, so we can just use exp instead of the full expressions.

cat(options()$exp)

The options command can also be used to set the recursion depth, i.e., options(expressions=500) for 500.

Try it online!

Giuseppe
sumber
1
You can save seven bytes by removing ressions due to partial matching with $.
Sven Hohenstein
1
More for future reference than as a contribution; is the consensus that you need to wrap this in cat()? R will output something in most circumstances, so is there a post somewhere clarifying good practice/logic to follow?
CriminallyVulgar
@SvenHohenstein dang, I always forget about that after I write R code in good style...Thank you!
Giuseppe
1
@CriminallyVulgar see for instance this post in meta; there's certainly some uncertainty about it.
Giuseppe
4

Octave, 25 22 20 bytes

2 bytes removed thanks to a suggestion by Sanchises

@max_recursion_depth

Anonymous function that outputs the value.

Try it online!

Luis Mendo
sumber
You don't need the (), as max_recursion_depth is also a function.
Sanchises
@Sanchises Thanks! You are right: even if the doc says it's a variable, it's actually a function
Luis Mendo
Your edit has turned this in a duplicate of the other Octave answer, hence my retained @ to keep it distinct (defining a function rather than REPL'ing the result).
Sanchises
@Sanchises Actually I just changed that, although for a different reason (the code should actually define a function)
Luis Mendo
Yeah the other answer is more like a program; I'm not sure if that should actually require disp (I would have included it, but that's my personal opinion on Octave REPL, and I am not sure of any meta consensus on that)
Sanchises
3

zsh, 24 bytes

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

Try it online! (See under debug)

bash, 24 bytes

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

Try it online! (See under debug)

ksh93, 27 bytes

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

Try it online! (See under debug)

dash, 27 bytes

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

Try it online! (Exceeds tio debug output, run it in your own shell)

Thor
sumber
1
Should i=0 and the echo not be included in your byte count?
Shaggy
@Shaggy: Perhaps, I have changed it to a more self-contained solution
Thor
1

Lua, 52 bytes

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

Try it online!

ATaco
sumber
@Shaggy in this case yes, because I use the name f. If this wasn't recursive I could get away with not having it
ATaco
Ah, I didn't spot the f in pcall.
Shaggy
why does your program stops at 200? here you can see that in that simple function it goes beyond 200. if you remove the -- you can confirm that it is still a recursive call with no optimizations
Felipe Nardi Batista
1

q/kdb+, 16 bytes

Solution:

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

Example:

/ 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

Explanation:

Try to recurse, increase x by one each time, if error, return 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
sumber
1

Excel-VBA, 26 Bytes

?Application.MaxIterations

Not recursion depth per-se, this actually outputs the maximum number of iterations for a cell in an Excel worksheet. Given that the output pertains to a language other than the language in which this is written, perhaps this is more appropriate:

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

Function f:f=Application.MaxIterations

As that can be called from a cell with

=f(

For VBA with no built in:

Excel-VBA, 53 44 40 bytes

-9 as variable no longer needs to be initialised or printed

-4 as code execution no longer has to be ended to avoid multiple prints

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

Call with s in the immediate window, outputs to cell A1 of the worksheet

(warning takes a while to run now, add Application.ScreenUpdating = False first)

Greedo
sumber
1

Lua, 45 37 bytes

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

Try it 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
sumber
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
sumber
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
sumber
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
sumber
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
sumber
0

Tcl, 49 bytes

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

Try it online!

sergiol
sumber
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
sumber
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
sumber