2012-01-20 9 views
26

में एक रिकर्सिव फाइबोनैकी फ़ंक्शन मैं क्लोजर के लिए एक नवागंतुक हूं जो देखना चाहता था कि सभी झगड़े क्या हैं। इसके लिए एक महसूस करने का सबसे अच्छा तरीका यह है कि कुछ सरल कोड लिखना है, मैंने सोचा कि मैं एक फाइबोनैकी समारोह से शुरू करूंगा।क्लोजर

मेरा पहला प्रयास था:

(defn fib [x, n] 
    (if (< (count x) n) 
    (fib (conj x (+ (last x) (nth x (- (count x) 2)))) n) 
    x)) 

इस मैं [0 1] जब फ़ंक्शन को कॉल के साथ एक्स बीज की जरूरत का उपयोग करें। मेरा सवाल यह है कि, इसे एक अलग फ़ंक्शन में लपेटने के बिना, क्या एक ऐसा फ़ंक्शन लिखना संभव है जो केवल तत्वों की संख्या को वापस ले लेता है?

कुछ पढ़ने करने से चारों ओर मुझे एक ही funcionality को प्राप्त करने के कुछ बेहतर तरीके को जन्म दिया:

(defn fib2 [n] 
    (loop [ x [0 1]] 
    (if (< (count x) n) 
     (recur (conj x (+ (last x) (nth x (- (count x) 2))))) 
     x))) 

और

(defn fib3 [n] 
    (take n 
    (map first (iterate (fn [[a b]] [b (+ a b)]) [0 1])))) 

वैसे भी, किसी और चीज से व्यायाम के लिए अधिक, किसी को भी यह कर सकते हैं पूरी तरह से रिकर्सिव फाइबोनैकी फ़ंक्शन के बेहतर संस्करण के साथ मेरी सहायता करें? या शायद एक बेहतर/अलग समारोह साझा करें?

(defn fib 
    ([n] 
    (fib [0 1] n)) 
    ([x, n] 
    (if (< (count x) n) 
     (fib (conj x (+ (last x) (nth x (- (count x) 2)))) n) 
     x))) 

समारोह परिभाषा इस प्रकार कहा जाता है बहु arity समारोह परिभाषा:

+5

fib3 इन –

उत्तर

16

आप पहली बार इस सवाल का जवाब करने के लिए। आप इसके बारे में यहां और जान सकते हैं: http://clojure.org/functional_programming

बेहतर फाइब फ़ंक्शन के लिए, मुझे लगता है कि आपका fib3 फ़ंक्शन काफी शानदार है और बहुत सारी कार्यात्मक प्रोग्रामिंग अवधारणाओं को दिखाता है।

+0

का सबसे क्लोज़रिश है यदि मैं सही ढंग से समझ गया हूं, तो ओवरलोडेड फ़ंक्शन के लिए एक फैंसी नाम की तरह दिखता है। महान काम करता है, धन्यवाद। – richc

+11

"मल्टी-आर्टी" "ओवरलोडेड" से अधिक विशिष्ट है। "बहु-धर्मार्थ" का अर्थ है "तर्कों की संख्या से प्रतिष्ठित," जबकि "अधिभारित" आमतौर पर "संख्या * या तर्क के प्रकार * द्वारा विशिष्ट" का अर्थ है। तो बहु-arity अधिभार विधियों का एक सबसेट है। –

+2

हम रिकर्सन के बिना एक अपरिवर्तनीय संस्करण कैसे लिख सकते हैं? – Dinesh

5

यह तेजी से और अच्छा है:

(def fib (lazy-cat [0 1] (map + fib (rest fib)))) 

से: http://squirrel.pl/blog/2010/07/26/corecursion-in-clojure/

+0

धन्यवाद निकिक, समझना मुश्किल है लेकिन बहुत रोचक है। – richc

+0

(डीफ फिब (आलसी-बिल्ली [0 1] (नक्शा + फिब (बाकी फाइब))) और (5 फिब लें) पहले 5 शब्दों को वापस कर देगा। दोबारा मैं इसे एक समारोह के रूप में लिखने के लिए संघर्ष कर रहा हूं: (defn fib ([n] (n fib ले लो)) ([] (आलसी-बिल्ली [0 1] (नक्शा + फिब (बाकी फाइब)))) ' टी काम नहीं – richc

+0

यदि कोड की उन 5 पंक्तियों को समझने में कठिनाई (मैं पेड़ एल्गोरिदम के बारे में बात कर रहा हूं) इस भाषा के बारे में कोई लाल झंडे नहीं उठाता है .... भी, क्या आप उस कोड में आवंटन की संख्या गिन सकते हैं? यह बहुत ज्यादा ऊंचा है। सिर्फ इसलिए कि रन टाइम स्केल रैखिक रूप से इसका मतलब यह नहीं है कि यह तेज़ है। –

1

एक अच्छा पुनरावर्ती परिभाषा है:

(def fib 
    (memoize 
    (fn [x] 
     (if (< x 2) 1 
     (+ (fib (dec (dec x))) (fib (dec x))))))) 

यह एक विशिष्ट अवधि के वापस आ जाएगी। विस्तार इस पहले n पदों वापस जाने के लिए मामूली बात है:

(take n (map fib (iterate inc 0))) 
3

आप (तुम कौन पूछने पर निर्भर करता है # 3 थोड़ा साफ करने के लिए थ्रश ऑपरेटर का उपयोग कर सकते हैं, कुछ लोग इस शैली से प्यार है, कुछ इसे नफरत है, मैं कर रहा हूँ बस उनका कहना है यह एक विकल्प है):

(defn fib [n] 
    (->> [0 1] 
    (iterate (fn [[a b]] [b (+ a b)])) 
    (map first) 
    (take n))) 

जिसके अनुसार, मैं शायद (take n) निकालने चाहते हैं और सिर्फ fib समारोह एक आलसी अनंत अनुक्रम होना है।

(def fib 
    (->> [0 1] 
    (iterate (fn [[a b]] [b (+ a b)])) 
    (map first))) 

;;usage 
(take 10 fib) 
;;output (0 1 1 2 3 5 8 13 21 34) 
(nth fib 9) 
;; output 34 
6

Clojure में यह प्रत्यावर्तन से बचने के लिए और बदले loop और recur विशेष रूपों का उपयोग की सलाह दी जाती वास्तव में है। यह बदले में एक पुनरावर्ती प्रक्रिया की तरह दिखता है, स्टैक ओवरफ्लो से बचने और प्रदर्शन में सुधार।

यहाँ कैसे आप इस तकनीक के साथ एक फाइबोनैचि अनुक्रम लागू होगी की एक उदाहरण है:

(defn fib [n] 
    (loop [fib-nums [0 1]] 
    (if (>= (count fib-nums) n) 
     (subvec fib-nums 0 n) 
     (let [[n1 n2] (reverse fib-nums)] 
     (recur (conj fib-nums (+ n1 n2))))))) 

loop निर्माण बाइंडिंग की एक श्रृंखला है, जो प्रारंभिक मान, और एक या अधिक शरीर रूपों प्रदान लेता है। इनमें से किसी भी बॉडी फॉर्म में, recur पर कॉल लूप को प्रदत्त तर्कों के साथ रिकर्सिव रूप से कॉल करने का कारण बनता है।

0

देर से आने वालों के लिए।

(defn fib 
    ([n] 
    (fib [0 1] n)) 
    ([x, n] 
    (if (< (count x) n) 
     (recur (conj x (apply + (take-last 2 x))) n) 
     x))) 
0

क्या इसके लायक है के लिए, लो इन वर्षों इसलिए, यहाँ 4Closure Problem #26: Fibonacci Sequence

(fn [x] 
    (loop [i '(1 1)] 
     (if (= x (count i)) 
      (reverse i) 
      (recur 
       (conj i (apply + (take 2 i))))))) 

करने के लिए अपने समाधान मैं नहीं है, किसी भी तरह से, यह लगता है: स्वीकृत जवाब इस बात का एक थोड़ा जटिल अभिव्यक्ति है इष्टतम या सबसे बेवकूफ दृष्टिकोण है। पूरे कारण से मैं 4Clojure पर अभ्यास के माध्यम से जा रहा हूं ... और Rosetta Code से कोड उदाहरणों पर उलझन सीखना है।

संयोग से मुझे अच्छी तरह से पता है कि फाइबोनैकी अनुक्रम औपचारिक रूप से 0 शामिल है ... कि यह उदाहरण loop [i '(1 0)] होना चाहिए ... लेकिन यह उनके spec से मेल नहीं खाएगा। न ही इस अभ्यास को लेबल करने के बावजूद अपने यूनिट परीक्षण पास करें। इसे 4 क्लोजर अभ्यास के लिए आवश्यकताओं के अनुरूप करने के लिए एक अज्ञात रिकर्सिव फ़ंक्शन के रूप में लिखा गया है ... जहां आपको किसी दिए गए अभिव्यक्ति के भीतर "खाली भरना" है। (मुझे दिमाग बेंडर का थोड़ा सा होने के लिए अज्ञात रिकर्सन की पूरी धारणा मिल रही है; मुझे लगता है कि (loop ... (recur ... विशेष रूप पर बाध्य है ... लेकिन यह अभी भी मेरे लिए एक अजीब वाक्यविन्यास है)।

मैं मूल पोस्टिंग में fib3 के संबंध में, [[आर्थर उलफेल्ड] की टिप्पणी भी लेगा, विचाराधीन भी। मैंने अभी तक क्लोजर के iterate का उपयोग किया है, अभी तक।

+0

उपयोगकर्ता संदर्भ के इस अन्य रूप को आजमा रहे हैं: @ [आर्थर उलफेल्ड] –

+0

एफडब्ल्यूआईडब्ल्यू: (एफएन [एन] (एन ले लो (नक्शा पहले (इटरेट (एफएन [[एबी]] [बी (+ एबी)]) '(1 1))))) ... इस समस्या के 4Clojure रूप के लिए भी काम करता है। –

0

यहाँ कम से कम पुनरावर्ती क्रिया मैं कंप्यूटिंग वें फिबोनैकी संख्या के लिए लेकर आए हैं जाता है:

(defn fib-nth [n] (if (< n 2) 
       n 
       (+ (fib-nth (- n 1)) (fib-nth (- n 2))))) 

हालांकि, पाश के साथ समाधान/प्रत्यावर्तन तेजी से सभी लेकिन के पहले कुछ मूल्यों के लिए किया जाना चाहिए ' n 'चूंकि क्लोजर लूप/रिकर पर पूंछ-अंत अनुकूलन करता है।