2017-01-03 12 views
5

में लूप इतनी धीमी क्यों है कि मैं संख्याओं के छोटे गैर-विभाजक (https://codegolf.stackexchange.com/questions/105412/find-the-smallest-number-that-doesnt-divide-n) को खोजने का प्रयास कर रहा हूं। का उपयोग करते हुए 'नाम दें' संस्करण के बाद ठीक से काम करता है: 5 2 19 और 23.रैकेट कोड

हालांकि

, निम्न संस्करण:

(f 24) 
(f 1234567) 
(f 12252240) 
(f 232792560) 

संस्करण से ऊपर की शीघ्र उत्पादन का उत्पादन:

(define (f1 m) 
    (let loop ((n 2)) 
    (cond 
     [(= 0 (modulo m n)) 
     (loop (+ 1 n))] 
     [else n]))) 

मैं के साथ परीक्षण कर रहा हूँ जो for लूप का उपयोग करता है, बहुत धीमा है और वास्तव में बड़ी संख्या के साथ स्मृति त्रुटि से क्रैश होता है:

(define (f2 m) 
    (for/first ((i (range 2 m)) 
       #:when (not (= 0 (modulo m i))) 
       #:final (not (= 0 (modulo m i)))) 
    i)) 

क्या दूसरे संस्करण के कोड में कुछ त्रुटि है या for लूप अक्षम है रैकेट में नामित की तुलना में?

+2

'श्रेणी 'को' इन-रेंज 'के साथ बदलने का प्रयास करें। –

+1

मुझे सीमा और सीमा के बीच इतना अंतर की उम्मीद नहीं थी। रेंज फ़ंक्शन के फायदे क्या हैं (छोटे नाम के अलावा)? रेंज बिल्कुल क्यों काम करता है? – rnso

+2

क्योंकि कभी-कभी आप एक सूची चाहते हैं, अनुक्रम नहीं। 'रेंज' एक सूची तैयार करता है, 'इन-रेंज' एक अनुक्रम उत्पन्न करता है (और इसके अलावा पुनरावृत्ति प्रदर्शन में सुधार के लिए 'के लिए' सहयोग करता है)। शायद 'रेंज' को 'for' के साथ सहयोग करने के लिए समायोजित किया जा सकता है। –

उत्तर

6

range फ़ंक्शन वास्तव में एक सूची आवंटित करता है, इसलिए आपके फ़ंक्शन का समय विशाल सूची आवंटन का प्रभुत्व है। बजाय in-range का उपयोग करें:

(define (f2 m) 
    (for/first ([i (in-range 2 m)] 
       #:when (not (= 0 (modulo m i))) 
       #:final (not (= 0 (modulo m i)))) 
    i)) 

भी देखें रैकेट गाइड में for performance पर अनुभाग विभिन्न अनुक्रम रूपों की सापेक्ष गति के बारे में अधिक नोट्स के लिए।

+0

अंतर बहुत बड़ा है! – rnso

0

मेरी राय में, आमतौर पर रिकॉर्ड्स रैकेट के लिए लूप की तुलना में अधिक उपयुक्त है। मैं इस तरह से समस्या से संपर्क करूंगा ...

(define start-counter 1) 

(define (f number counter) 
    (cond [(not (= (modulo number counter) 0)) counter] 
     [else (f number (add1 counter))])) 

(define (f2 number) 
    (f number start-counter)) 
+0

आप बस अपने मुख्य कार्य को परिभाषित कर सकते हैं: (परिभाषित करें (एफ संख्या (काउंटर 1)) ...; यह काउंटर को 1 का डिफ़ॉल्ट मान देता है और इसके साथ आपको पहले और तीसरे परिभाषित कथन/एफएन की आवश्यकता नहीं है। हालांकि, मेरे प्रश्न में 'फॉर' लूप का कारण धीमा है 'इन-रेंज' फ़ंक्शन के बजाय 'श्रेणी' के उपयोग के कारण स्पष्ट रूप से है। – rnso