2012-10-24 5 views
5

मैं हाल ही में एक समस्या का प्रयास कर रहा हूं। और इस मामले में मुझे कुछ समस्याएं आ रही हैं।एक सूची उत्पन्न करना जो दाएं स्थानांतरित तत्वों द्वारा बनाई गई है n बार

Input: generatingListforRightShifting 2 [1,2,3,4,5,6,7,8] 
Output: [[1,2,3,4,5,6,7,8],[8,1,2,3,4,5,6,7],[7,8,1,2,3,4,5,6]] 

जैसा कि आप समझते हैं कि यह प्रोग्राम सही दिशा में एक तत्व को स्थानांतरित करेगा। पहला तर्क इंगित करता है कि यह कितनी बार स्थानांतरित होगा। एक नौसिखिया के रूप में मैं इसे कुछ प्रसिद्ध सूची कार्यों को हल करने की कोशिश कर रहा हूं। और रिकर्सन का उपयोग कर। लेकिन मेरे लिए पुनरावृत्ति विचार स्पष्ट नहीं है। मेरा कोड है:

generatingListforRightShifting' _ []=[] 
generatingListforRightShifting' 0 x=x 
generatingListforRightShifting' n xs= newList where 
         newList=takeWhile(\i->[1..n] 
              <=n)(reverse(take 
              i(reverse xs))++reverse(drop i(reverse xs))) 

मैं समझता हूं कि मैं जो मुख्य गलती कर रहा हूं वह हिस्सा ले रहा है। लेकिन मैं एन बार के माध्यम से कैसे पुन: प्रयास कर सकते हैं। मैंने पहले से ही एक प्रोग्राम बनाया है जो सीधे इनपुट स्थानांतरित करता है इनपुट: जेनरेटिंग लिस्टफॉर राइटशफ्टिंग 2 [1,2,3,4,5,6,7,8] आउटपुट: [7,8,1,2,3, 4,5,6] लेकिन जब मैं पिछले सभी स्थानांतरण पाने की कोशिश करता हूं तो मैं नहीं कर सकता।

क्या कोई मेरी मदद कर सकता है। यदि आप मुझे हल करने का विचार देते हैं तो मैं भी आपका स्वागत करता हूं।

उत्तर

2

आप रिक्त रूप से "शिफ़्ट" को परिभाषित कर सकते हैं: shift 0 एक नो-ऑप है, shift 1+n (x:xs)shift n xs है।

कुछ की तरह:

shift 0 = \x -> x 
shift n = \[email protected](x:xs) -> (shift (n-1) xs) 

-- example: 
sh3 = shift 3   

फिर 'घुमाने' समस्या आसान हो जाता है:

rotate n = \lst -> (shift lst) ++ (take n lst) 
+0

कि 'drop' होगा, कोई टी "शिफ्ट", जो "घुमाने" के लिए है। –

+0

@ डैनियल फिशर: हाँ - मुझे बहुत देर हो गई, मैंने सवाल को आधा पढ़ा। "घुमाने" एक अच्छा नाम है। – xtofl

+0

thnx से u xtolf। वास्तव में एक शुरुआत के रूप में मैं सिर, पूंछ, दोहराना जैसे सरल संचालन का उपयोग करने की कोशिश करता हूं। इस कारण से मैं इस समस्या का प्रयास करता हूं। मैं कोड को भारी रूप से छोटा नहीं करना चाहता हूं। थोड़ी देर के बाद fllowing पोर्टिन "(रिवर्स (ले लो (रिवर्स एक्सएस)) ++ रिवर्स (ड्रॉप i (रिवर्स एक्सएस))" एकल समय स्थानांतरण के लिए काम करता है। मैं इसे कई बार स्थानांतरित करने के लिए उपयोग करना चाहता हूं। क्या आप मेरी मदद कर सकते हैं? बीटीडब्ल्यू, थैक्स और बहुत बहुत thnx fr ur effrt – sabu

3

यह और अधिक सामान्यतः बजाय घूर्णन स्थानांतरण के रूप में जाना जाता है। एक बार सूची को घुमाने के लिए सरल है, क्योंकि last element और sublist of all elements but the last प्राप्त करने के तरीके हैं।

rotateOnce lst = (last lst):(init lst) 

यह भी ध्यान रखें कि घूर्णन दो बार घूमने के बराबर है दो बार एक बार।

rotateN 0 lst = [lst] 
rotateN n lst = lst : rotateN (n-1) ((last lst):(init lst)) 

: इसलिए, विधि पिछले परिणाम से एक प्रत्यावर्तन के रूप में बस लागू किया जा सकता (नोट:। यह है कि ज्यादातर सर्वोत्कृष्ट समाधान नहीं हो सकता है)

+3

'अगर आप मुझसे पूछें तो ले लें (एन + 1) $ पुनरावृत्त घुमाओ एक बार lst'। –

+0

thnx केनी.लेकिन यू knw मैं अपनी खुराक पूरी तरह से chnge नहीं करना चाहता हूँ। मैं takewhile के हिस्से को संपादित करना चाहता हूँ। यह "(रिवर्स (एनआई (रिवर्स एक्सएस) ले लो ++ रिवर्स (ड्रॉप एन (रिवर्स एक्सएस))" "तत्व को स्थानांतरित करने के लिए चलाया जाता है। अब मैं रिकर्सिव कॉल के बिना इस भाग का कई बार उपयोग करना चाहता हूं। Thnx बहुत ...... लेकिन क्या आप मुझे रोक सकते हैं? – sabu

1

मैं वर्तमान दृष्टिकोण, जो बहुत है छोड़ देगी जटिल। इसके बजाय, ऑपरेशन के विभिन्न घटकों को सारणित करने पर ध्यान केंद्रित करें। यदि आप भागों में ऑपरेशन तोड़ते हैं, तो आप देखेंगे कि दो सममित घटक हैं: सूची को बाईं ओर घुमाएं, और सूची को दाईं ओर घुमाएं। ऑपरेशन जिसे आप परिभाषित करना चाहते हैं, सही सूची में कुछ सूची में निर्दिष्ट संख्या को दोहराता है। यह पता चलता है कि वांछित आपरेशन लेने द्वारा परिभाषित किया जा सकता दोहराव हैं या तो छोड़ दिया या सही रोटेशन की एक निर्धारित संख्या। उदाहरण के लिए,

left :: [a] -> [a] 
left [] = [] 
left xs = tail xs ++ [head xs] 

right :: [a] -> [a] 
right [] = [] 
right xs = last xs : init xs 

shiftL :: Int -> [a] -> [[a]] 
shiftL n = take n . iterate left 

shiftR :: Int -> [a] -> [[a]] 
shiftR n = take n . iterate right 
+0

लाइन 3 में, मुझे लगता है कि आपको [हेड एक्सएस] की आवश्यकता है, सिर एक्सएस नहीं। – mhwombat

+0

सही, धन्यवाद। सुधार के लिए संपादित किया गया। – danportin

1

cycle का उपयोग करते हुए यहाँ अच्छा लगता है:

shifts n xs = take (n+1) $ shifts' (cycle xs) 
    where 
    len = length xs 
    shifts' ys = take len ys:shifts' (drop (len-1) ys) 
+0

thnx है। लेकिन आपका प्रोग्राम त्रुटि दिखाता है। – sabu

+0

@SaugataBose क्षमा करें, इसे ठीक करें। – is7s

2

आप पसंद करते हैं करने के लिए है कि हम अपने कोड से फिर से शुरू ठीक लग रहे हैं, तो चलो अपने कोड पर एक नजर है।सबसे पहले, मुख्य सूची काट:

reverse (take i (reverse xs)) ++ reverse (drop i (reverse xs)) 

अब reverse (take i (reverse xs)) सूची, के अंत से i तत्वों लेता है, लेकिन आप इस लक्ष्य को हासिल करने के लिए दो बार सूची रिवर्स, और यह बेहतर हो drop (length xs - i) xs करने के लिए होगा। इसी प्रकार, आप reverse (drop i (reverse xs))) को take (length xs - i) xs के रूप में कार्यान्वित कर सकते हैं। यही कारण है कि हमें

drop (length xs - i) xs ++ take (length xs - i) xs 

देता है अब आप अपने कोड \i->[1..n]<=n मतलब नहीं है, क्योंकि यह सूची [1..n]n साथ , जो काम नहीं कर सकता है। मुझे लगता है कि आप एक लूप बनाने की कोशिश कर रहे हैं जहां i 1 से n तक चलता है, जो एक अच्छी योजना है। के लोगों को हम चाहते थे प्राप्त करने के लिए एक सूची समझ का उपयोग करते हैं:

[drop (length xs - i) xs ++ take (length xs - i) xs | i <- [1 .. length xs], i <= n] 

लेकिन अब हम 1 से सूची की लंबाई के चला रहे हैं, लेकिन दूर, जो बेहतर लिखा जाएगा n ऊपर संख्या फेंकने

[drop (length xs - i) xs ++ take (length xs - i) xs | i <- [1..n]] 

यह n को length xs से अधिक होने की अनुमति देता है, लेकिन मुझे वहां कोई बड़ी समस्या नहीं दिखाई देती है, हम इसे पहले देख सकते हैं।

सूचना अब हम केवल प्रपत्र (length xs - i) में i का उपयोग कर कि कर रहे हैं, और वास्तव में हम हम चाहिए की तुलना में length xs एक भयंकर बहुत अधिक recalculating रहे हैं, इसलिए बजाय n करने के लिए 1 से i रन दे की, और length xs - i का उपयोग कर, कारण है कि हम सिर्फ length xs से length xs - n करने के लिए j=length xs -i तो j रन की जरूरत नहीं है:

[drop j xs ++ take j xs | j <- [length xs,length xs - 1 .. length xs - n]] 

जो काम करता है क्योंकि उदाहरण [6,5..1] == [6,5,4,3,2,1]

के लिए

यह neater होगा

let l = length xs in 
    [drop j xs ++ take j xs | j <- [l,l - 1 .. l - n]] 

करने के लिए या शायद आप take से अधिक आप गणित करना पसंद चाहते हैं, इसलिए हम इस्तेमाल कर सकते हैं:

let l = length xs in 
    take n [drop j xs ++ take j xs | j <- [l,l - 1 .. 0]] 

जो आप को रोकने के अतिरिक्त लाभ है जब आप शुरुआत में वापस आते हैं तो को रोककर बहुत अधिक कर रहे हैं।

मैं generatingListforRightShifting से rotationsR करने के लिए अपने समारोह का नाम बदलने चाहते हैं,

rotationsR n xs = let l = length xs in 
    take n [drop j xs ++ take j xs | j <- [l,l - 1 ..]] 

कौन सा rotationsR 6 [1..4] == [[1,2,3,4],[4,1,2,3],[3,4,1,2],[2,3,4,1],[1,2,3,4]] देता है दे रही है।

वाम रोटेशन सरल दिखेगा:

rotationsL n xs = take n [drop j xs ++ take j xs | j <- [0..length xs]] 

विषयांतर: मैं अपने आप को मदद नहीं कर सकता है, माफ करना, और मैं फिर से शुरू कर दिया।

मैं अभी भी यह सब छोड़ने पसंद नहीं है और हर एक समय लग रहा है, मैं नहीं बल्कि अगले एक दूसरे को (cycle xs) को xs की असीम कई प्रतियां पॉप चाहते हैं और असीम कि के कई tails ले उन सब को काटना सही लंबाई, लेकिन बस आपको पहला एन:

रोटेशन एल 'एन xs = let l = लंबाई xs एन ले लो। मानचित्र (एल ले लो)। पूंछ चक्र $ XS

क्योंकि आलसी मूल्यांकन की, केवल cycle xs की एक निश्चित राशि कभी गणना की जाती है, लेकिन यह एक चलाने के लिए और चला सकते हैं: rotationsL' 10 [1..4] आप देता है:

[[1,2,3,4],[2,3,4,1],[3,4,1,2],[4,1,2,3],[1,2,3,4],[2,3,4,1],[3,4,1,2],[4,1,2,3],[1,2,3,4],[2,3,4,1]] 

यह सही करने के लिए अच्छा होगा उस तरह की roations भी, लेकिन यह काम नहीं करता है क्योंकि मुझे एक अनंत सूची के अंत में शुरू करना होगा और अपना रास्ता वापस काम करना होगा। के अपने रिवर्स पुन: उपयोग करते हैं, ले आपको क्या चाहिए, चाल फिर रिवर्स, हालांकि:

rotationsR' n xs = let l = length xs in 
    take n . map (reverse.take l) . tails . cycle . reverse $ xs 

Undigression: यदि आप अपने मूल कोड को और अधिक बारीकी से चिपके रहते हैं चाहते हैं, तो आप कर सकते हैं

generatingListforRightShifting n xs = 
    [reverse (take i (reverse xs)) ++ reverse (drop i (reverse xs)) | i <- [1..n]] 
1

मैं splitAt का उपयोग कर बहुत सीधे आगे होने के लिए एक बाएँ रोटेशन लगता है:

import Data.Tuple (swap) 
rotateLeft n = uncurry (++) . swap . splitAt n 

> rotateLeft 2 "Hello World!" 
>>> "llo World!He" 
संबंधित मुद्दे