Özyineleme ile golf nasıl
Özyineleme, en hızlı seçenek olmasa da, çoğu zaman en kısa yoldur. Genel olarak, özüm özüm, özümün zorluğun daha küçük bir kısmına sadeleştirilebilmesi durumunda, özellikle girdi bir sayı veya bir dize olduğunda en kısadır. Örneğin, eğer f("abcd")
hesaplanabilir "a"
ve f("bcd")
bu özyinelemeyi kullanmak genellikle en iyi,.
Örneğin, faktoring atın:
n=>[...Array(n).keys()].reduce((x,y)=>x*++y,1)
n=>[...Array(n)].reduce((x,_,i)=>x*++i,1)
n=>[...Array(n)].reduce(x=>x*n--,1)
n=>{for(t=1;n;)t*=n--;return t}
n=>eval("for(t=1;n;)t*=n--")
f=n=>n?n*f(n-1):1
Bu örnekte, özyineleme açıkça, diğer seçeneklerden çok daha kısadır.
Charcodes toplamına ne dersiniz:
s=>[...s].map(x=>t+=x.charCodeAt(),t=0)|t
s=>[...s].reduce((t,x)=>t+x.charCodeAt())
s=>[for(x of(t=0,s))t+=x.charCodeAt()]|t // Firefox 30+ only
f=s=>s?s.charCodeAt()+f(s.slice(1)):0
Bu daha zordur, ancak doğru şekilde uygulandığında özyinelemenin 4 bayttan tasarruf ettiğini görebiliriz .map
.
Şimdi farklı özyineleme türlerine bakalım:
Ön özyineleme
Bu genellikle en kısa özyineleme türüdür. Giriş iki parçaya bölünmüş olan a
ve b
ve fonksiyon bir şey hesaplar a
ve f(b)
. Faktöriyel örneğimize geri dönelim:
f=n=>n?n*f(n-1):1
Bu durumda, a
bir N , b
olan , n-1 , ve geri değerdir a*f(b)
.
Önemli not: Tüm özyinelemeli işlevler , giriş yeterince küçük olduğunda özyinelemeyi durduracak bir yola sahip olmalıdır . Faktöriyel fonksiyonu olarak, bu kontrol edilir n? :1
girişi, yani eğer 0 dönüş 1 çağırmadan f
tekrar.
Post-özyineleme
Özyineleme sonrası özyineleme öncesiyle benzer, ancak biraz farklıdır. Giriş iki parçaya bölünmüş olan a
ve b
ve fonksiyon bir şey hesaplar a
ve ardından çağırır f(b,a)
. İkinci argüman genellikle varsayılan bir değere sahiptir (örn.f(a,b=1)
).
Nihai sonuçla özel bir şey yapmanız gerektiğinde ön yineleme iyidir. Örneğin, bir sayı artı 1'in faktörlemesini istiyorsanız:
f=(n,p=1)=>n?f(n-1,n*p):p+1
Bununla birlikte, o zaman bile, post- her zaman başka bir işlev içinde özyinelemeyi kullanmaktan daha kısa değildir:
n=>(f=n=>n?n*f(n-1):1)(n)+1
Peki ne zaman daha kısa? Bu örnekteki özyinelemenin, özyinelemeden önce değilken, işlev argümanlarının çevresinde parantez gerektirdiğini fark edebilirsiniz. Genel olarak, her iki çözüm de argümanlar etrafında parantez gerektiriyorsa, özyineleme sonrası yaklaşık 2 bayt daha kısadır:
n=>!(g=([x,...a])=>a[0]?x-a.pop()+g(a):0)(n)
f=([x,...a],n=0)=>a[0]?f(a,x-a.pop()+n):!n
(buradaki programlar bu cevaptan alınmıştır) )
En kısa çözümü nasıl bulabilirim?
Genellikle en kısa yöntemi bulmanın tek yolu hepsini denemektir. Bu içerir:
Ve bunlar sadece en yaygın çözümlerdir; En iyi çözüm, bunların bir kombinasyonu veya tamamen farklı bir şey olabilir . En kısa çözümü bulmanın en iyi yolu her şeyi denemek .