2012-03-19 14 views
5

मैं अपने हास्केल क्लास के लिए समाधान ढूंढ रहा हूं।विभाजन सूची और sublist से योग बनाते हैं?

मेरे पास संख्याओं की एक सूची है और मुझे सूची के प्रत्येक भाग के लिए एसयूएम वापस करने की आवश्यकता है। भागों को 0 से विभाजित किया गया है। मुझे FOLDL फ़ंक्शन का उपयोग करने की आवश्यकता है।

उदाहरण:
प्रारंभिक सूची [1,2,3,0,3,4,0,5,2,1]
sublist [[1,2,3], [3,4], [5,2,1]]
परिणाम [6,7,7]

मैं प्रारंभिक सूची में 0 को खोजने के लिए एक समारोह है:

findPos list = [index+1 | (index, e) <- zip [0..] list, e == 0] 

(रिटर्न [4,6] प्रारंभिक सूची के लिए उदाहरण से)

और FOLDL के साथ SUM बनाने के लिए फ़ंक्शन:

sumList list = foldl (+) 0 list 

लेकिन मैं पूरी तरह से यह एक साथ रखा करने में विफल:/

---- मेरा समाधान
अंत में मैं कुछ पूरी तरह से अलग है कि तुम लोगों का सुझाव दिया पाया।
इसे बनाने के लिए पूरे दिन मुझे ले गया:/

groups :: [Int] -> [Int] 
groups list = [sum x | x <- makelist list] 

makelist :: [Int] -> [[Int]] 
makelist xs = reverse (foldl (\acc x -> zero x acc) [[]] xs) 

zero :: Int -> [[Int]] -> [[Int]] 
zero x acc | x == 0 = addnewtolist acc 
      | otherwise = addtolist x acc 

addtolist :: Int -> [[Int]] -> [[Int]] 
addtolist i listlist = (i : (head listlist)) : (drop 1 listlist) 

addnewtolist :: [[Int]] -> [[Int]] 
addnewtolist listlist = [] : listlist 
+0

मुझे लगता है कि 'परिणाम' '[6,7,7]' के बजाय '6,7,8] होना चाहिए। – Landei

उत्तर

2

अब जब आपने अपनी समस्या पूरी की है, तो मैं आपको थोड़ा कम वर्बोज संस्करण दिखा रहा हूं। Foldr इस समस्या के बारे में मेरी राय में बेहतर लगता है *, लेकिन क्योंकि आपने foldl के लिए कहा था, मैं आपको दोनों कार्यों का उपयोग करके अपना समाधान दिखाऊंगा।

इसके अलावा, अपने उदाहरण गलत प्रतीत हो रहा, [5,2,1] की राशि 8, नहीं 7.

foldr संस्करण।

makelist' l = foldr (\x (n:ns) -> if x == 0 then 0:(n:ns) else (x + n):ns) [0] l 

इस संस्करण में, हम सूची पार, यदि वर्तमान तत्व (एक्स) एक 0 है, तो हम संचायक सूची में एक नया तत्व जोड़ (एन: एनएस)। अन्यथा, हम वर्तमान तत्व का मान संचयक के सामने तत्व के मान में जोड़ते हैं, और इस मान के साथ संचयक के सामने के मूल्य को प्रतिस्थापित करते हैं। कदम से

कदम:

  1. acc = [0], x = 1. Result is [0+1]
  2. acc = [1], x = 2. Result is [1+2]
  3. acc = [3], x = 5. Result is [3+5]
  4. acc = [8], x = 0. Result is 0:[8]
  5. acc = [0,8], x = 4. Result is [0+4,8]
  6. acc = [4,8], x = 3. Result is [4+3,8]
  7. acc = [7,8], x = 0. Result is 0:[7,8]
  8. acc = [0,7,8], x = 3. Result is [0+3,7,8]
  9. acc = [3,7,8], x = 2. Result is [3+2,7,8]
  10. acc = [5,7,8], x = 1. Result is [5+1,7,8] = [6,7,8]

वहाँ तुम्हारे पास है!

और foldl संस्करण। उपरोक्त के समान काम करता है, लेकिन एक उलटा सूची बनाता है, इसलिए सूची को अपरिवर्तित करने के लिए इस फ़ंक्शन की शुरुआत में रिवर्स का उपयोग।

makelist l = reverse $ foldl (\(n:ns) x -> if x == 0 then 0:(n:ns) else (x + n):ns) [0] l 

* सही से सूची तह एक छोड़ दिया गुना के साथ एक उलट सूची मेरी विधि का उपयोग कर उत्पादन की अनुमति देता है, विपक्ष (:) समारोह स्वाभाविक रूप से इस्तेमाल किया जा रहा। (वहाँ की संभावना बाईं गुना संस्करण है कि मुझे लगता है कि इस triviality समाप्त नहीं सोचा था क्या करने के लिए एक सरल तरीका है।)

+0

कमाल, धन्यवाद :) – m4recek

6

मैं के बाद से इस लगता है जैसे कि यह एक होमवर्क असाइनमेंट हो सकता है, बल्कि एक पूर्ण समाधान की तुलना में, आप कुछ संकेत देने के लिए जा रहा हूँ।

मुझे आपके द्वारा सुझाए गए चरणों का टूटना पसंद है। पहले चरण के लिए (सूचियों की सूची में शून्य मार्करों की संख्याओं की सूची से जाकर), मैं एक स्पष्ट रिकर्सन करने का सुझाव देता हूं; एक टेम्पलेट के लिए इस प्रयास करें:

splits []  = {- ... -} 
splits (0:xs) = {- ... -} 
splits (x:xs) = {- ... -} 

तुम भी groupBy दुरुपयोग कर सकते हैं यदि आप सावधान कर रहे हैं।

दूसरे चरण के लिए, ऐसा लगता है कि आप लगभग वहां हैं; आपको जिस अंतिम चरण की आवश्यकता है वह map :: (a -> b) -> ([a] -> [b]) फ़ंक्शन पर नज़र डालना है, जो एक सामान्य कार्य करता है और इसे सूची के प्रत्येक तत्व पर चलाता है।

बोनस अभ्यास के रूप में, आप इस बारे में सोचना चाहेंगे कि आप एक शॉट में एक ही गुना के रूप में पूरी चीज कैसे कर सकते हैं। यह संभव है - और यहां तक ​​कि बहुत मुश्किल नहीं है, अगर आप foldr/foldl पर विभिन्न तर्कों के प्रकारों के माध्यम से ट्रैक करना चाहते हैं!

परिवर्धन के बाद से सवाल बदल दिया है:

के बाद से ऐसा लगता है कि आप एक समाधान बाहर काम किया है, अब मैं आराम से कुछ विफल देने लग रहा है। =)

मैंने दो संभावित कार्यान्वयन का सुझाव दिया; एक जो कदम-दर-चरण चलाता है, जैसा कि आपने सुझाव दिया था, और दूसरा जो एक बार में जाता है।कदम-दर-कदम एक ऐसा दिखाई दे सकता:

splits []  = [] 
splits (0:xs) = [] : splits xs 
splits (x:xs) = case splits xs of 
    []  -> [[x]] 
    (ys:yss) -> ((x:ys):yss) 

groups' = map sum . splits 

या इस तरह:

splits' = groupBy (\x y -> y /= 0) 
groups'' = map sum . splits' 

सब-एट-एक बार संस्करण इस प्रकार दिखाई देंगे:

accumulate 0 xs  = 0:xs 
accumulate n (x:xs) = (n+x):xs 

groups''' = foldr accumulate [0] 

करने के लिए जांचें कि आप इन्हें समझते हैं, यहां कुछ अभ्यास हैं जिन्हें आप आजमा सकते हैं:

  • splits और splits'[1,2,3,0,4,5] के साथ क्या करते हैं? [1,2,0,3,4,0]? [0]? []? Ghci में अपनी भविष्यवाणियों की जांच करें।
  • भविष्यवाणी करें groups (आपके सहित) के चार संस्करणों में से प्रत्येक [] या [1,2,0,3,4,0] जैसे इनपुट के लिए आउटपुट, और फिर ghci में अपनी भविष्यवाणी का परीक्षण करें।
  • अन्य कार्यान्वयनों में से एक के व्यवहार को प्रदर्शित करने के लिए groups''' संशोधित करें।
  • groups''' के बजाय foldl का उपयोग करने के लिए संशोधित करें।
+0

और यदि आप होमवर्क नहीं हैं तो आप हैकेज से विभाजित पैकेज का उपयोग कर सकते हैं और 'splitOn [0]' का उपयोग कर सकते हैं। – Jedai

+0

हाय, मदद के लिए धन्यवाद :) दुख की बात है कि यह मेरे लिए बहुत उपयोगी नहीं था। मैं अतिथि हूं कि मुझे "डमी के लिए उदाहरण" की आवश्यकता है। मैं वास्तव में हैकेल के लिए नया हूं इसलिए मुझे ऐसी समस्याएं थीं: "सूची में पहली सूची में कुछ कैसे जोड़ें" और "प्रकार कैसे लिखें" आदि .. वैसे भी, क्या आप कृपया सुझाए गए समाधान को लिख सकते हैं? मुझे दिलचस्पी है कि यह कैसे होना चाहिए :) – m4recek

+0

@ user1279158 हो गया। –

1

आप पहले से ही इसे हल के रूप में, एक और संस्करण:

subListSums list = reverse $ foldl subSum [0] list where 
    subSum xs 0 = 0 : xs 
    subSum (x:xs) n = (x+n) : xs 

(यह मानते हुए आपको लगता है कि सूची में केवल गैर-ऋणात्मक संख्याएं हैं)

+0

कोड में गैर-नकारात्मक धारणा कहां दिखाई देती है? –

+0

यदि किसी समूह की संख्या शून्य तक पहुंच जाएगी, तो यह शून्य अगले समूह द्वारा "ओवरराइट" किया जाएगा, इसलिए यह योग अंतिम सूची में दिखाई नहीं देगा। – Landei

+0

मुझे लगता है कि आपने अपना कोड गलत समझा होगा! आपके कोड का कोई भी हिस्सा जांचता है कि वर्तमान चल रहा योग '0' के बराबर है या नहीं; इसके अलावा, एक और अनुभवजन्य स्तर पर, 'subListSums [2, -2,0,2, -2]' ghci में सही बात करने लगता है। –

संबंधित मुद्दे