पुनरावृत्ति के साथ गोल्फ कैसे करें
पुनरावृत्ति, हालांकि सबसे तेज़ विकल्प नहीं है, बहुत कम बार होता है। आम तौर पर, पुनरावृत्ति सबसे कम होती है यदि समाधान चुनौती के एक छोटे हिस्से के समाधान को सरल बना सकता है, खासकर अगर इनपुट एक संख्या या एक स्ट्रिंग है। उदाहरण के लिए, यदि f("abcd")
इसकी गणना की जा सकती है "a"
और f("bcd")
, आमतौर पर पुनरावृत्ति का उपयोग करना सबसे अच्छा है।
उदाहरण के लिए, तथ्यात्मक को लें:
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
इस उदाहरण में, पुनरावृत्ति स्पष्ट रूप से किसी अन्य विकल्प की तुलना में कम है।
कैसे चारकोड के योग के बारे में:
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
यह एक पेचीदा मामला है, लेकिन हम देख सकते हैं कि जब इसे सही तरीके से लागू किया जाता है, तो पुनरावृत्ति 4 बाइट्स बचाती है .map
।
अब विभिन्न प्रकार के पुनरावर्तन पर नजर डालते हैं:
पूर्व प्रत्यावर्तन
यह आमतौर पर सबसे छोटी प्रकार की पुनरावृत्ति है। इनपुट दो भागों में विभाजित है a
और b
, और समारोह के साथ कुछ की गणना करता है a
और f(b)
। हमारे तथ्यात्मक उदाहरण पर वापस जा रहे हैं:
f=n=>n?n*f(n-1):1
इस मामले में, a
है n , b
है n-1 , और दिए गए मान है a*f(b)
।
महत्वपूर्ण नोट: सभी पुनरावर्ती कार्यों में इनपुट छोटा होने पर पुनरावर्तन को रोकने का एक तरीका होना चाहिए । फैक्टोरियल फंक्शन में, इसे नियंत्रित किया जाता है n? :1
, अर्थात यदि इनपुट 0 है , तो फिर से कॉल किए बिना 1 लौटें f
।
पोस्ट-प्रत्यावर्तन
पुनरावृत्ति पूर्व पुनरावृत्ति के समान है, लेकिन थोड़ा अलग है। इनपुट दो भागों में विभाजित है a
और b
, और समारोह के साथ कुछ की गणना करता है a
, तो कहता है f(b,a)
। दूसरे तर्क में आमतौर पर एक डिफ़ॉल्ट मान (यानी f(a,b=1)
) होता है।
पूर्व-पुनरावृत्ति अच्छा है जब आपको अंतिम परिणाम के साथ कुछ विशेष करने की आवश्यकता होती है। उदाहरण के लिए, यदि आप संख्या 1 का भाज्य चाहते हैं:
f=(n,p=1)=>n?f(n-1,n*p):p+1
फिर भी, हालांकि, पोस्ट- किसी अन्य फ़ंक्शन के भीतर पूर्व-पुनरावृत्ति का उपयोग करने से हमेशा छोटा नहीं होता है:
n=>(f=n=>n?n*f(n-1):1)(n)+1
तो यह कब कम है? आप देख सकते हैं कि इस उदाहरण में पोस्ट-रिकरशन को फ़ंक्शन तर्कों के आसपास कोष्ठक की आवश्यकता होती है, जबकि पूर्व-पुनरावृत्ति नहीं हुई थी। आम तौर पर, यदि दोनों समाधानों को तर्कों के चारों ओर कोष्ठकों की आवश्यकता होती है, तो पुनरावृत्ति 2 बाइट्स के आसपास होती है:
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
( इस उत्तर से लिए गए कार्यक्रम )
सबसे छोटा उपाय कैसे खोजे
आमतौर पर सबसे छोटी विधि खोजने का एकमात्र तरीका उन सभी को आज़माना है। यह भी शामिल है:
- लूप्स
.map
(तार के लिए, या तो [...s].map
या s.replace
; संख्या के लिए है, तो आप कर सकते हैं एक श्रेणी बनाएं )
- ऐरे की समझ
- पूर्व-पुनरावर्तन (कभी-कभी इन विकल्पों में से एक के भीतर)
- पोस्ट-प्रत्यावर्तन
और ये सिर्फ सबसे आम समाधान हैं; सबसे अच्छा समाधान इनमें से एक संयोजन हो सकता है, या यहां तक कि कुछ पूरी तरह से अलग भी हो सकता है । सबसे छोटा उपाय खोजने का सबसे अच्छा तरीका सब कुछ करने की कोशिश करना है ।