Độ sâu đệ quy tối đa [đóng]


15

Ngôn ngữ của bạn có độ sâu đệ quy tối đa (MRD) không?

Giả sử ngôn ngữ của bạn có MRD = 500

Viết mã tìm độ sâu đệ quy và đưa ra giá trị chính xác

Đối với trường hợp trên, chương trình của bạn (hoặc chức năng) sẽ xuất 500

Code-Golf Câu trả lời ngắn nhất sẽ thắng!


3
@cairdcoinheringaahing ... "tìm thấy độ sâu đệ quy" có nghĩa là mã hóa cứng không hợp lệ

6
Tôi nghĩ vấn đề chính với thách thức này là không được phép in giá trị mã hóa cứng, nhưng đọc biến hệ thống mã hóa cứng là ổn. Cả hai không thực sự khác biệt đáng kể với tôi.
DJMcMayhem

2
@DJMcMayhem tích hợp nhiều lần sử dụng thông tin được mã hóa cứng. Thử thách này cho phép tích hợp sẵn.

7
Vâng, đó là quan điểm của tôi. Cả hai chỉ đơn giản là đọc một giá trị được mã hóa cứng, nhưng một cái được cho phép và cái kia thì không.
DJMcMayhem

3
@DJMcMayhem tích hợp trong mathicala cũng có thể có cờ swiss (tôi đã thấy thử thách này ở đây), nhưng đăng cờ tương tự như jpg là không hợp lệ.

Câu trả lời:



19

Python 3 , 40 byte

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

Hãy thử trực tuyến!

Mà không cần đọc nó từ nội dung. Chúng tôi bắt đầu ở 2 thay vì 1 vì mệnh đề ngoại trừ được chạy một cấp trước khi nó bị lỗi. Đây là một byte ngắn hơn trong python 2, tất nhiên.


1
Bạn không cần 3 byte để gọi f
8 bit trên toàn thế giới

Theo mặc định, 8 lần gửi như một chức năng được chấp nhận. Trừ khi câu hỏi cấm họ cụ thể, bạn có thể gửi một chức năng có thể sử dụng lại như một giải pháp. Bạn sẽ nhận thấy rằng nhiều câu trả lời khác cho câu hỏi này cũng làm điều tương tự.
FryAmTheEggman

15

JavaScript (Babel) , 35 33 29 byte

f=_=>do{try{-~f()}catch(e){}}
  • 2 byte được lưu nhờ Neil.

Hãy thử ở đây hoặc sử dụng Đoạn trích bên dưới để kiểm tra evalthay vì do.

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


Cổng Japt , 24 byte

Nó không thực sự đáng để đăng bài này như một giải pháp riêng biệt vì về cơ bản, nó giống hệt nhau.

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

Kiểm tra nó


Giải trình

Bản thân JavaScript không có giới hạn đệ quy mỗi se, thay vào đó giới hạn được áp dụng bởi trình thông dịch (tức là trình duyệt) - điều tốt là chúng tôi xác định ngôn ngữ theo vòng thông dịch viên của họ ở đây! Trong số các yếu tố khác, giới hạn có thể thay đổi tùy theo trình duyệt và bộ nhớ khả dụng, bị ảnh hưởng bởi các hoạt động được thực hiện. Đoạn trích sau minh họa điểm cuối cùng đó, sử dụng 5 phiên bản khác nhau của giải pháp này mà tôi đã trải qua. Như bạn có thể thấy từ 2 thử nghiệm gần đây nhất, trong Chrome, ít nhất, ngay cả thứ tự hoạt động cũng có thể tạo ra sự khác biệt.

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

Do đó, do đó chúng tôi không có sự thuận tiện của hằng số hoặc phương pháp để làm việc. Thay vào đó, chúng ta sẽ tạo ra một chức năng tự gọi liên tục trước đó, cuối cùng, xuất hiện. Ở dạng đơn giản nhất đó là:

f=_=>f()

Nhưng điều đó không giúp ích nhiều cho chúng tôi cho thử thách này vì nó chỉ gây ra lỗi tràn mà không có dấu hiệu cho thấy fbản thân đã gọi bao nhiêu lần . Chúng ta có thể tránh được những lỗi bằng cách trying lời kêu gọi fliên tục và catching khi nó không thành công:

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

Không có lỗi, nhưng vẫn không có giá trị trả về bao nhiêu lần hàm quản lý tự gọi trước khi thất bại, vì catchthực tế không làm gì cả. Hãy thử đánh giá try / catchtuyên bố:

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

Bây giờ chúng tôi đã có một giá trị được trả về (và, bởi vì đây là mã golf, đã tiết kiệm cho chúng tôi một vài byte so với sử dụng thực tế return). Tuy nhiên, giá trị được trả lại là undefinedcatchkhông làm gì cả. May mắn cho chúng tôi -~undefined==1-~n==n+1do đó, bằng cách bật một -~cuộc gọi trước f, về cơ bản chúng tôi đã nhận được -~-~ ... -~-~undefined, với một -~cuộc gọi khác được chuẩn bị trước cho mỗi cuộc gọi, cho chúng tôi số lần fđược gọi.

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

Giải pháp tuyệt vời, vì tôi cho rằng bạn không có quyền truy cập vào độ sâu đệ quy trong JS!
Zacharý

3
33 byte:f=_=>eval('try{-~f()}catch(e){}')
Neil

@Neil: Tôi thấy phiên bản 34 byte của bạn khi tôi đang đi ngủ và tự đá mình vì không nghĩ về nó. Phiên bản 33 byte đó được lấy cảm hứng. Cảm ơn.
Xù xì

13

Mathicala (không tích hợp), 20 byte

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

Bỏ qua ;tính toán sẽ 1+$IterationLimit(có lẽ vì Mathicala đuôi tối ưu hóa chức năng). Hoặc 0 //. x_ -> x + 1tính toán ReplaceRepeatedmặc định MaxIteration, nghĩa là, 65536(lớn hơn cả hai giá trị ở trên).

(Đây là đoạn mã đánh giá kết quả. Tuy nhiên, giải pháp Mathicala khác cũng vậy)


10

J, 8 byte

1+$: ::]

Hãy thử trực tuyến!

Vì vậy, tôi thực sự không biết làm thế nào để thực thi một động từ mà không có bất kỳ đầu vào nào và một số tìm kiếm ngắn gọn (cũng như trực giác cá nhân) làm cho nó có vẻ như điều đó là không thể. Nếu có, xin vui lòng cho tôi biết cách thực hiện và tôi sẽ xóa hoặc cập nhật câu trả lời của mình. Nó không thực sự có ý nghĩa cho một động từ được đưa ra không có đầu vào, mặc dù. Trong trường hợp này, hàm được đưa ra mong đợi 0, đầu vào "trống" mặc định cho số nguyên. Tôi có thể thay đổi nó để sử dụng mảng trống ( 0$0) nếu bạn nghĩ rằng điều đó phù hợp hơn.

Chỉnh sửa: OP đã cho phép hàm lấy 0.

Giải trình

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

Điều này gọi chính nó một cách đệ quy, thêm 1 vào đầu vào (dự kiến ​​0) cho đến khi nó gặp lỗi ngăn xếp. Khi có lỗi, nó gọi bất lợi ( ]nhận dạng chính xác) trên đầu vào, chỉ là 0.

Nhân tiện, không gian là cần thiết .


1
đầu ra 6000 trên máy của tôi. fwiw tôi nghĩ đây là một trò chơi công bằng, nhưng bạn luôn có thể đưa ra câu trả lời của mình(1+$: ::]) 0
Jonah

@Jonah điểm công bằng, tôi đã quen với việc gửi các chức năng. Trên máy của tôi, nó là 6666 đủ kỳ lạ.
cole

6660 trên iPad pro. Mát mẻ!
Aganju

Cách nó xử lý độ sâu đệ quy tối đa dường như phụ thuộc phiên bản - trên điện thoại của tôi, tôi nhận được 5999 (dường như bị tắt bởi 1). Trên iPad của tôi (thật lòng tôi không nhớ model nào), nó chỉ bị hỏng.
cole

9

Python 3 , 41 32 byte

import sys
sys.getrecursionlimit

Hãy thử trực tuyến!

Đã lưu 9 byte nhờ @FryAmTheEggman!

34 byte

from sys import*
getrecursionlimit

35 byte

__import__('sys').getrecursionlimit

2 người cuối cùng là nhờ @totallyhuman


32 byte , 34 byte35 byte . Bạn chọn đi. : P
hoàn toàn là

@FryAmTheEggman vâng tôi có thể, cảm ơn bạn!
caird coinheringaahing

Tôi đang gặp lỗi (ít nhất là trên TIO) khi cố chạy lần đầu tiên 2.
Shaggy

@Shaggy bạn sẽ phải trao đổi các dòng cho cái đầu tiên, quá trình nhập diễn ra sau để cho phép nội dung được phân bổ tên. Tôi sẽ cập nhật liên kết.
caird coinheringaahing

8

C (gcc, Linux x64), 180 133 byte

-4 byte nhờ @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)));}

Hãy thử trực tuyến!

Cài đặt trình xử lý SIGSEGV (tín hiệu 11) với ngăn xếp tín hiệu thay thế (kích thước tối thiểu MINSIGSTKSZlà 2 KB, cờ SA_ONSTACKlà 0x08000000), sau đó gọi một hàm không có đối số và không có biến cục bộ đệ quy cho đến khi ngăn xếp tràn. Điều thú vị là độ sâu đệ quy tối đa khác nhau giữa các lần chạy, có thể là do ASLR.

Độ sâu đệ quy tối đa trong C phụ thuộc vào rất nhiều yếu tố. Trên hệ thống Linux 64 bit thông thường, kích thước ngăn xếp mặc định là 8 MB và căn chỉnh ngăn xếp là 16 byte, do đó bạn có được độ sâu đệ quy khoảng 512K cho các chức năng đơn giản.

Cũng lưu ý rằng chương trình trên không hoạt động -O2vì tối ưu hóa cuộc gọi đuôi.


1
+1! You can save 4 bytes by incrementing c and calling exit and sigaction as parameters. This doesn't make a noticable difference on the result: TIO link
scottinet

6

Java 8, 131 51 48 47 43 bytes

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

-80 bytes thanks to @Nevay. I tried a method instead of program as well, but made a mistake so ended up with a full program.. Now it's a method.
-3 bytes thanks to @Neil by making use of finally instead of catch(Error e).
-5 byte thanks to @Nevay again.

Explanation:

Try it here.

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 bytes: int c(){try{return-~c();}catch(Error e){return 1;}}
Nevay

2
@Nevay You often post excellent answers in comments. You could post them as answers, and get some reputations. Nothing forbids any question from having several Java answers. ;-)
Olivier Grégoire

2
int c(){int n=1;try{n=-~c();}finally{return n;}} saves 3 bytes but gives me a different answer?
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

Octave, 19 bytes

max_recursion_depth

Usage:

octave:1> max_recursion_depth
ans =  256

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!


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!


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)


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!


@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

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)



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.


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.


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.


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
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.