प्रारंभिक त्रुटि: अनंत recursion
अपने कोड के माध्यम से कदम:
sumint :: Int -> Int
अरे, एक प्रकार हस्ताक्षर। आपने धमाल मचाया।
sumint x
| x==0 = 0
एक बेस केस, ठंडा।
| x==1 = 1
एक पूरी तरह से अनावश्यक मामला। ठीक है, यकीन है ... को छोड़कर। 1 भी नहीं है तो हम इसे योग में क्यों शामिल कर रहे हैं? यह शून्य होना चाहिए (या पूरी तरह से हटा दिया जाना चाहिए)।
| (x `mod` 2 == 0) && (x >= 2) = x + (sumint x-2)
इस मुद्दे का मांस यहां है। 1. एक्स भी महान है। 2. एक्स सकारात्मक है, हाँ। परिणाम x + (sumint x) - 2
नहीं है!
- त्रुटि 1: नोटिस फ़ंक्शन एप्लिकेशन ऑपरेटरों की तुलना में बाघ को बांधता है, इसलिए यह
x + sumint (x-2)
होना चाहिए।
यह आपके स्टैक ओवरफ़्लो का कारण है। sumint 2 == 2 + (sumint 2) - 2 + (sumint 2) -2 + (sumint 2) -2 + ...
, याय अनंत रिकर्सन।
| (x `mod` 2 /= 0) && (x >= 1) = x + (sumint x-1)
एक और मामला ... विषम ... सकारात्मक ... लेकिन हम एक्स में क्यों जुड़ रहे हैं? आप बाधाओं को जोड़ना चाहते हैं, बाधाओं को नहीं। तो एक ही समय में ऊपर समस्या दूर करने की हम पाते हैं:
- त्रुटि 2: यदि आप निर्धारित
x
अजीब है, x
में शामिल न करें। बस sumint (x-1)
का उपयोग करें।
फिर आप मामलों से बाहर हैं। क्या होता है यदि एक्स सकारात्मक नहीं है? आपको (दूसरा) मामला चाहिए।
| otherwise = 0
अगला समस्या: कोई संचय
समस्या अब आप एक बड़े thunk (unevaluated गणना) का निर्माण कर रहे हैं के बजाय परिणाम आप प्रगति के रूप में अर्जित होने के कारण निरंतर अंतरिक्ष में सक्रिय है। सूचना है कि अगर हम के लिए कहते हैं, अपने गणना का विस्तार, 6 हम पाते हैं:
sumint 6 = 6 + sumint (6-2)
= 6 + 4 + sumint (4-2)
= 6 + 4 + 2 + sumint (2-2)
= 6 + 4 + 2 + 0
आप वास्तव में नहीं है उन सभी अतिरिक्त अलग रखने के लिए, चाहते हैं कि उसे इस तरह के रूप में एक संचायक में पारित करने के लिए अच्छा होगा:
sumint x = go x 0
where
go n accumulator
| n <= 0 = accumulator
| odd n = go (n-1) accumulator
| otherwise = go (n-2) (accumulator + n)
साइड नोट: अन्य स्टैक ओवरफ्लो नागरिक संचयक को सख्त बनाने का उल्लेख कर सकते हैं, जो कि अच्छा रूप है। मैं वर्तमान चर्चाकर्ता को उस चर्चा के साथ विचलित नहीं करना चाहता हूं। अनुकूलन का उपयोग कर नोटिस, -O2
, पर्याप्त है।
मुहावरेदार समाधान
उपरोक्त सभी समाधान नहीं बल्कि अत्यधिक शब्द हैं। सामान्य ऑपरेशन, फ़ंक्शन और संचयक के साथ एक सूची में पुनरावृत्त, fold
का एक प्रकार है। मोड़ कार्यात्मक प्रोग्रामिंग में आम तौर पर कई अत्यधिक अनुकूलित संरचना ट्रैवर्सल में से एक है। इस मामले में एक "सख्त बाएं गुना" सामान्य उम्मीदवार है (Data.List
से)। l
का मतलब है कि l
का मतलब है कि foldl'
'प्राइम ('
) का मतलब है कि यह सख्त है।
sumint n = foldl' (+) 0 [val | val <- [0..n], even val]
यहां हमने अपनी राशि प्राप्त करने के लिए सूची में तब्दील किया। ब्याज की सूची बनाने के लिए हमने सूची समझ का उपयोग किया - पहले 0..n
से मूल्यों की गणना करना और किसी भी मान को छोड़ना जो even
को पूर्ववत नहीं करता है।
हम आगे इस को साफ और sum
समारोह और सूची समझ है कि 2 से कदम, इस प्रकार हमें केवल evens आप इच्छा देने का उपयोग करके इसे सुधार कर सकते हैं:
sumint n = sum [0,2..n]
ग्रेट, धन्यवाद। वास्तव में मुझे क्या चाहिए। –
छोटे विवरण: 'go'' को 'sumint'' की परिभाषा में '(+)' के साथ प्रतिस्थापित किया जाना चाहिए जो 'foldl'' का उपयोग करता है। मैं यह संपादन कर दूंगा लेकिन परिवर्तन 6 वर्णों से कम है। – liminalisht