Maksimum Özyineleme Derinliği [kapalı]


15

Dilinizin maksimum özyineleme derinliği (MRD) var mı?

Diyelim ki dilinizde MRD = 500 var

Özyineleme derinliğini bulan ve kesin değeri veren bir kod yazın

Yukarıdaki durum için programınızın (veya fonksiyonunuzun) 500 çıkışı olmalıdır

Code-Golf En kısa cevap kazanıyor!


3
@cairdcoinheringaahing ... "özyineleme derinliğini bulur",

6
Bu zorlukla ilgili temel sorun, sabit kodlanmış bir değerin yazdırılmasına izin verilmemesi, ancak sabit kodlanmış bir sistem değişkeninin okunmasının iyi olmasıdır. İkisi benim için gerçekten farklı görünmüyor.
James

2
@DJMcMayhem yerleşik kodlanmış bilgileri birçok kez kullanır. Bu meydan okuma yerleşik yapılara izin verir.

7
Evet, bu benim açımdan. Her ikisi de sadece sabit kodlanmış bir değer okuyor, ancak birisine izin verilir ve diğerine izin verilmiyor.
James

3
Matematikada yerleşik @DJMcMayhem de swiss bayrağı (burada bu zorluğu gördüm) olabilir, ancak jpg ile aynı bayrağı gönderme geçersiz.

Yanıtlar:



19

Python 3 , 40 bayt

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

Çevrimiçi deneyin!

Onu sadece yerleşmeden okumadan. 1 cümlesi yerine 2 yerine başlarız; Bu elbette python 2'de bir bayt daha kısadır.


1
3 bayt aramanıza gerek yok f
8bitwide

@ 8bitwide gönderimleri varsayılan olarak kabul edilir. Soru özellikle onları yasaklamıyorsa, yeniden kullanılabilir bir işlevi çözüm olarak gönderebilirsiniz. Bu sorudaki diğer birçok cevabın aynı şeyi yaptığını göreceksiniz.
FryAmTheEggman

15

JavaScript (Babel) , 35 33 29 bayt

f=_=>do{try{-~f()}catch(e){}}
  • Neil sayesinde 2 bayt kurtardı.

Burada deneyin veya evalyerine test etmek için aşağıdaki Snippet'i kullanın do.

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


Japt bağlantı noktası, 24 bayt

Bunu, aslında özdeş olduğu için ayrı bir çözüm olarak göndermeye değmez.

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

Dene


açıklama

JavaScript'in kendisinde bir özyineleme sınırı yoktur, bunun yerine sınır, yorumlayıcı (yani tarayıcı) tarafından uygulanır - dilleri tercümanları tarafından burada tanımladığımız iyi bir şey! Diğer faktörlerin yanı sıra, sınır, gerçekleştirilen işlemlerden etkilenen tarayıcıya ve kullanılabilir belleğe göre değişebilir. Aşağıdaki Snippet, bu çözümün 5 farklı sürümünü kullandığım son noktayı göstermektedir. Son 2 testten görebileceğiniz gibi, Chrome'da en azından işlemlerin sırası bile fark yaratabilir.

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

Bu nedenle, çalışmak için bir sabit veya yöntem kolaylığına sahip değiliz. Bunun yerine, nihayetinde toparlanmadan önce kendini sürekli çağıran bir işlev yaratacağız. En basit haliyle:

f=_=>f()

Ancak bu meydan okuma için bize pek fazla faydası yoktur çünkü yalnızca kaç kez fkendini çağırdığına dair hiçbir belirti olmadan bir taşma hatası atar . Biz hatayı önleyebilirsiniz trying çağrıya fsürekli ve catchbaşarısız olduğunda ing:

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

Hata yok, ancak işlev başarısız olmadan önce kaç kez kendini çağırmayı başardığının dönüş değeri yok, çünkü catchaslında hiçbir şey yapmıyor. İfadeyi değerlendirmeyi deneyelim try / catch:

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

Şimdi döndürülen bir değere sahibiz (ve bu kod golf olduğundan, gerçek bir kullanarak kendimizi birkaç bayt kurtardık return). Geri döndürülen değer undefinedyine de , çünkü catchhiçbir şey yapmıyor. Neyse ki bizim için -~undefined==1ve -~n==n+1böylece, -~çağrının önüne bir haşhaş ile f, aslında -~-~ ... -~-~undefined, -~her çağrı ile başa bir başkasıyla , kaç kez fçağrıldığını vererek aldık .

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

Güzel çözüm, çünkü JS'de bir yineleme derinliği yerleşikine erişiminiz olmadığını varsayıyorum!
Zacharý

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

@Neil: Yatağa giderken 34 baytlık versiyonunuzu gördüm ve düşünmediğim için kendimi tekmeledim. Bu 33 baytlık versiyondan ilham alındı. Teşekkürler.
Shaggy

13

Mathematica (yerleşik yok), 20 bayt

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

;Hesaplamayı atlamak 1+$IterationLimit(muhtemelen Mathematica işlevi en iyi duruma getirdiği için). Alternatif olarak , varsayılan değerini (yani, yukarıdaki her iki değerden daha büyük) 0 //. x_ -> x + 1hesaplayın .ReplaceRepeatedMaxIteration65536

(Bu, sonucu değerlendiren bir kod snippet'idir. Ancak diğer Mathematica çözümü de)


10

J, 8 bayt

1+$: ::]

Çevrimiçi deneyin!

Yani, aslında herhangi bir girdi olmadan bir fiilin nasıl yürütüleceğini bilmiyorum ve bazı kısa arama (hem de kişisel sezgi) bunu mümkün değil gibi görünüyor. Öyleyse, lütfen nasıl yapılacağını bana bildirin, cevabımı siler veya güncelleyeceğim. Yine de bir fiile girdi verilmemesi gerçekten mantıklı değil. Bunun ışığında, verilen fonksiyon 0, tamsayılar için varsayılan "boş" giriş bekler . 0$0Eğer daha uygun olduğunu düşünüyorsanız muhtemelen boş dizi ( ) kullanmak için değiştirebilirsiniz .

Düzenleme: OP, işlevin 0 almasına izin verdi.

açıklama

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

Bu, kendini bir yığın hatasına çarpana kadar girişe 1 (0 bekleniyor) ekleyerek kendini yinelemeli olarak çağırır. Hata verdiğinde ], yalnızca 0 olan girişteki olumsuz ( -right kimliğini) çağırır .

Bu arada, alan gerekli .


1
makinemde 6000 çıktı. fwiw bunun adil bir oyun olması gerektiğini düşünüyorum, ancak her zaman sadece cevabınızı yapabilirsiniz(1+$: ::]) 0
Jonah

@Jonah fair point, işlevleri göndermeye alışkınım. Makinemde 6666 tuhaf bir şekilde yeterli.
cole

Bir iPad pro'da 6660. Güzel!
Aganju

Maksimum özyineleme derinliğini işleme biçimi sürüme bağlı görünüyor - telefonumda 5999 alıyorum (1 ile kapalı gibi görünüyor). İPad'imde (dürüstçe hangi modeli hatırlamıyorum), sadece çöküyor.
cole

9

Python 3 , 41 32 bayt

import sys
sys.getrecursionlimit

Çevrimiçi deneyin!

@FryAmTheEggman sayesinde 9 bayt tasarruf edildi!

34 bayt

from sys import*
getrecursionlimit

35 bayt

__import__('sys').getrecursionlimit

Son 2 @totallyhuman sayesinde


32 bayt , 34 bayt ve 35 bayt . İstediğini al. : P
totallyhuman

@FryAmTheEggman evet yapabilirim, teşekkür ederim!
caird coinheringaahing

İlk 2'yi çalıştırmaya çalışırken (en azından TIO'da) bir hata alıyorum
Shaggy

@Shaggy, birincisi için hatları değiştirmelisiniz, içe aktarma işlemine, yerleşkenin bir ad atanmasına izin vermek için devam eder. Bağlantıyı güncelleyeceğim.
caird coinheringaahing

8

C (gcc x64), 180 133 bayt

@Scottinet sayesinde -4 bayt

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)));}

Çevrimiçi deneyin!

Alternatif sinyal yığınına sahip bir SIGSEGV (sinyal 11) işleyicisi yükler (minimum boyut MINSIGSTKSZ2 KB, bayrak SA_ONSTACK0x08000000), ardından bağımsız değişkenler olmadan bir işlevi çağırır ve yığın taşana kadar özyinelemeli olarak çağırmaz. Maksimum özyineleme derinliğinin, muhtemelen ASLR nedeniyle, çalışmalar arasında değişmesi ilginçtir.

C'deki maksimum tekrarlama derinliği elbette birçok faktöre bağlıdır. Tipik bir 64 bit Linux sisteminde varsayılan yığın boyutu 8 MB ve yığın hizalaması 16 bayttır, böylece basit işlevler için yaklaşık 512K özyineleme derinliği elde edersiniz.

Ayrıca yukarıdaki programın -O2kuyruk çağrısı optimizasyonu nedeniyle çalışmadığını unutmayın .


1
1! Artırıp cçağırarak exitve sigactionparametre olarak 4 bayt kaydedebilirsiniz . Bu, sonuçta belirgin bir fark
yaratmaz

6

Java 8, 131 51 48 47 43 bayt

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

@Nevay sayesinde -80 bayt . Ben de program yerine bir yöntem denedim, ama bu yüzden tam bir program ile sona erdi bir hata yaptım .. Şimdi bir yöntem.
-3 sayesinde bayt @Neil yararlanılarak finallyyerine catch(Error e). Tekrar @Nevay
sayesinde -5 bayt .

Açıklama:

Burada deneyin.

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

2
@Nevay Sık sık yorumlarda mükemmel yanıtlar gönderirsiniz. Onları cevap olarak gönderebilir ve itibar kazanabilirsiniz. Hiçbir şey, herhangi bir sorunun birkaç Java yanıtı almasını engelleyemez. ;-)
Olivier Grégoire

2
int c(){int n=1;try{n=-~c();}finally{return n;}}3 bayt kaydeder ama bana farklı bir cevap verir mi?
Neil

2
47 bayt:int c(){int n=1;try{n+=c();}finally{return n;}}
Nevay

1
43 bayt:int d;int c(){try{c();}finally{return++d;}}
Nevay

4

Oktav, 19 bayt

max_recursion_depth

Kullanımı:

octave:1> max_recursion_depth
ans =  256

4

R , 32 26 18 bayt

Sven Hohenstein sayesinde -8 bayt : $kısmi eşleştirme yapacağız, bu yüzden exptam yerine kullanabilirsiniz expressions.

cat(options()$exp)

optionsKomut ayrıca, yineleme derinliğini, yani ayarlamak için kullanılabilecek options(expressions=500)500 için.

Çevrimiçi deneyin!


1
İle kısmi eşleme nedeniyle kaldırarak yedi bayt kaydedebilirsiniz . ressions$
Sven Hohenstein

1
Gelecekteki referanslar için bir katkı olarak değil; cat () 'da sarmanız gereken fikir birliği nedir? R çoğu durumda bir şey çıktılar , bu yüzden takip etmek için iyi uygulama / mantığı açıklayan bir yazı var mı?
CriminallyVulgar

@SvenHohenstein dang, R kodunu iyi bir tarzda yazdıktan sonra her zaman unuturum ... Teşekkürler!
Giuseppe

1
@CriminallyVulgar örneğin bu yayını meta olarak görür ; bu konuda kesinlikle bir belirsizlik var.
Giuseppe

4

Oktav , 25 22 20 bayt

Sanchises'in önerisi sayesinde 2 bayt kaldı

@max_recursion_depth

Değeri veren anonim işlev.

Çevrimiçi deneyin!


Ayrıca bir işlev olduğu ()gibi max_recursion_depth, gerekmez .
17'de Sanchises

@ Teşekkürler! Haklısın: Doktor değişken olduğunu söylese bile , aslında bir işlev
Luis Mendo

Düzenlemeniz bunu diğer Octave cevabının bir kopyası olarak değiştirdi, bu yüzden @onu farklı tutmak için sakladım (sonucu REPL'lemek yerine bir işlev tanımlamak).
Sanchises

@Sanchises Aslında ben sadece farklı bir nedenle (kod aslında bir işlevi tanımlamak gerekir) rağmen, değiştirdim
Luis Mendo

Evet, diğer cevap daha çok bir program gibidir; Bunun gerçekten gerekli olup olmadığından emin değilim disp(bunu dahil ederdim, ancak bu benim Octave REPL hakkındaki kişisel görüşüm ve bu konuda herhangi bir meta konsensüs olduğundan emin değilim)
Sanchises

3

zsh, 24 bayt

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

Çevrimiçi deneyin! (Hata ayıklama bölümüne bakın)

bash, 24 bayt

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

Çevrimiçi deneyin! (Hata ayıklama bölümüne bakın)

ksh93, 27 bayt

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

Çevrimiçi deneyin! (Hata ayıklama bölümüne bakın)

tire, 27 bayt

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

Çevrimiçi deneyin! (Tio hata ayıklama çıktısını aşar, kendi kabuğunuzda çalıştırır)


1
Meli i=0ve echosizin bayt sayısına dahil edilmeyecektir?
Shaggy

@Shaggy: Belki de daha bağımsız bir çözüm olarak değiştirdim
Thor

1

Lua , 52 bayt

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

Çevrimiçi deneyin!


@Shaggy bu durumda evet, çünkü f adını kullanıyorum. Bu özyinelemesiz olsaydım sahip
olamamıştım

Ah, nokta değildi fin pcall.
Shaggy

programınız neden 200'de duruyor? burada bu basit fonksiyonda 200'ün ötesine geçtiğini görebilirsiniz. kaldırırsanız --, hala optimizasyon olmadan yinelemeli bir çağrı olduğunu onaylayabilirsiniz
Felipe Nardi Batista

1

q / kdb +, 16 bayt

Çözüm:

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

Misal:

/ 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

Açıklama:

Tekrarlamaya çalışın, x'i her seferinde bir artırın, hata varsa x döndürün.

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

?Application.MaxIterations

Özyinelemeli derinlik değil, aslında Excel çalışma sayfasındaki bir hücrenin maksimum yineleme sayısını çıkarır. Çıktının bunun yazıldığı dilden başka bir dile ait olduğu düşünüldüğünde, belki de daha uygundur:

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

Function f:f=Application.MaxIterations

Bu şekilde bir hücreden

=f(

Dahili olmayan VBA için:

Excel-VBA, 53 44 40 bayt

-9 değişkenin artık başlatılmasına veya yazdırılmasına gerek olmadığından

Birden fazla yazdırmayı önlemek için kod yürütme işleminin artık sona ermesi gerekmediğinden -4

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

Hemen pencerede s ile çağırın, çalışma sayfasının A1 hücresine çıkar

(uyarının çalışması biraz zaman alır, Application.ScreenUpdating = Falseönce ekleyin )



1

Clojure, 72 55 48 bayt

Atomdan kurtularak -23 bayt

@Madstap sayesinde -7 bayt. Kullanmaya geçildi fnüzerinde defve #()ve prüzerinde println.

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

Telefonuma yazdı ve test etti. Clojure REPL uygulaması bana 13087 derinlik verdi.

Temel çözüm. Bir SO atılana kadar her bir geri çekilme için bir sayaç artırılarak geri alma. Fırlatıldığında, sayacın değeri yazdırılır.


Sen kullanarak 5 bayt kaydedebilirsiniz pryerine println. Ayrıca fn şöyle yaparak -2 bayt: ((fn f[x](,,,))0)yerine (def f #(,,,))(f 0).
madstap

@madstap Teşekkürler. Değişiklikleri birazdan yapacağım.
Ağustos 17'de Carcigenicate

1

VBA, her tür, 41 39 bayt

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

?A()Hemen penceresinde veya çalışma sayfası işlevi olarak kullanarak arayın .

Not: @Greedo'nun cevabı sistemimde 3666 değerini döndürürken, Excel-VBA'da 4613 değerini döndürür (en yüksek değer maksimum olmalıdır). Görünüşe göre Office programları arasında da değişir (Access-VBA 4622, Word-VBA 4615'i döndürür)

Düzenleme: Sanırım VBA parantezleri otomatik olarak ekler, bu yüzden onları kaldırıldı.


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
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.