2010-12-27 5 views
8

मैं हास्केल के लिए नया हूँ, और मैं थोड़ा कोशिश कर रहा हूँ:हास्केल प्रधानमंत्री परीक्षण

isPrime :: Integer->Bool 
isPrime x = ([] == [y | y<-[2..floor (sqrt x)], mod x y == 0]) 

मैं कुछ प्रश्न हैं।

  1. क्यों जब मैं .hs लोड करने का प्रयास, WinHugs कहते हैं: (Floating Integer, RealFrac Integer) के उदाहरण isPrime की परिभाषा के लिए आवश्यक है?
  2. दुभाषिया सही सेट में एक तत्व होता है, तो इसे तुरंत बंद हो जाता है या इसे पूरी तरह से तैयार की गणना करता है? मुझे लगता है आपको पता है कि मेरा क्या आशय है।

मेरी अंग्रेजी के बारे में खेद है।

उत्तर

17

1) समस्या यह है कि sqrt में (Floating a) => a -> a है, लेकिन आप एक इंटीजर को तर्क के रूप में उपयोग करने का प्रयास करते हैं। तो आपको अपने इंटीजर को फ़्लोटिंग में पहले कनवर्ट करना होगा, उदा।sqrt (fromIntegral x)

2) लिख कर मैं कोई कारण नहीं क्यों == आलसी नहीं होना चाहिए देखते हैं, लेकिन एक खाली संग्रह के लिए परीक्षण के लिए आप, null समारोह (जो निश्चित रूप से आलसी है उपयोग कर सकते हैं के रूप में यह अनंत सूची पर काम करता है):

isPrime :: Integer->Bool 
isPrime x = null [y | y<-[2..floor (sqrt (fromIntegral x))], x `mod` y == 0] 

लेकिन अधिक मूर्खतापूर्ण समाधान प्राप्त करने के लिए, समस्या को छोटी उप-समस्याओं में विभाजित करें। सबसे पहले, हम y * y के साथ y सभी तत्वों की सूची की जरूरत < = एक्स:

filter (\y -> x `mod`y == 0) (takeWhile (\y -> y*y <= x) [2..]) 

फिर हम उस सूची अगर जांच करने की आवश्यकता:

takeWhile (\y -> y*y <= x) [2..] 

फिर हम केवल तत्वों है कि एक्स विभाजित की जरूरत है रिक्त है:

isPrime x = null (filter (\y -> x `mod`y == 0) (takeWhile (\y -> y*y <= x) [2..])) 

और अगर यह आपके लिए lispy को लग रहा है, $

isPrime x = null $ filter (\y -> x `mod` y == 0) $ takeWhile (\y -> y*y <= x) [2..] 
0 के साथ कोष्ठक में से कुछ की जगह अतिरिक्त स्पष्टता के लिए

आप lambdas "आउटसोर्स" कर सकते हैं:

isPrime x = not $ any divisible $ takeWhile notTooBig [2..] where 
    divisible y = x `mod`y == 0 
    notTooBig y = y*y <= x 
+0

अंतिम घोषणा सभी संख्याओं के लिए 2 से अधिक या बराबर के लिए काम करती है। 1 के लिए यह गलत कहता है कि यह प्राइम है, क्योंकि 1 प्राइम नहीं है। – Elmex80s

7
  1. क्योंकि sqrt प्रकार Floating a => a -> a है। इसका मतलब है कि इनपुट Floating प्रकार होना चाहिए और आउटपुट एक ही प्रकार का होगा। दूसरे शब्दों में x एक Floating प्रकार की जरूरत है। हालांकि आपने को Integer टाइप करने के लिए घोषित किया है, जो Floating प्रकार नहीं है। इसके अलावा floor, एक RealFrac प्रकार की जरूरत है ताकि x कि होने के लिए और साथ ही जरूरत है।

    त्रुटि संदेश को ठीक है कि उस Integer एक Floating प्रकार (बनाने एक उदाहरण Floating Integer (और RealFrac के लिए एक ही) को परिभाषित करते हुए द्वारा।

    पाठ्यक्रम इसमें से

    इस मामले में सही दृष्टिकोण नहीं है पता चलता है। बल्कि आप fromIntegral का प्रयोग कर एक Real को x कन्वर्ट करने के लिए (जो Floating और RealFrac का एक उदाहरण है) और फिर sqrt है कि दे।

  2. हां। जैसे ही == देखता है के रूप में सही संकार्य एक है टी से कम एक तत्व है, यह जानता है कि यह [] के बराबर नहीं है और इस प्रकार False देता है।

    कहा जा रहा है कि, null यह जांचने के लिए एक और बेवकूफ तरीका है कि कोई सूची [] == से खाली है या नहीं।

+2

बेवकूफ समाधानों के लिए, मैं सुझाव दूंगा। वर्ग संख्या के लिए इंटेग्रल 'से। 1 और 'सभी (\ y -> x \' mod \ 'y/= 0) [...]'। – delnan

1
दूसरी बात के बारे में

, यह बंद हो जाता है, उदाहरण के लिए:

[] == [x | x <- [1..]] 

रिटर्न False

+3

'[x | एक्स <- [1 ..]] '' [1 ..] 'बीटीडब्ल्यू जैसा ही है। – sepp2k

-2
  1. मैं WinHugs पूर्णांक और आदि के लिए एक मॉड्यूल आयात करने के लिए की आवश्यकता है ... इंट का प्रयास करें
  2. दुभाषिया कुछ भी गणना नहीं करेगा जब तक आप कॉल नहीं करते isPrime 32 तो यह अभिव्यक्ति की आलस्य की गणना करेगा।

पीएस आपका isPime कार्यान्वयन सबसे अच्छा कार्यान्वयन नहीं है!

+0

1) इंटीजर के लिए "मॉड्यूल आयात [आईएनजी] मुद्दा नहीं है; मुद्दा यह है कि उनकी परिभाषा के अनुसार, "उदाहरण के फ्लोटिंग इंटीजर, रीयलफ्रैक इंटीजर) की परिभाषा के लिए आवश्यक है", जैसे WinHugs ने कहा। 2) हाँ, और ...?यह इतना अप्रासंगिक है, मुझे यकीन नहीं है कि इसका जवाब कैसे दिया जाए; सबसे पहले, परिभाषा को ठीक करें ताकि यह काम करे, फिर इसका उपयोग कैसे करें इसके बारे में चिंता करें। पीएस) ओपी का प्राइम कार्यान्वयन सबसे अच्छा नहीं है, आंत यह एक "वह" लागू है! उसकी व्याख्या करने में मदद करें, अपना खुद का लिखें, "या जीटीएफओ!" – BMeph

+0

1) आप सही हैं, मैंने बहुत लंबे समय तक हास्केल का उपयोग नहीं किया है। 2) मैं उसे इतनी तुच्छ पीएस की आलस्य के बारे में बताने की कोशिश कर रहा था) वह एक छात्र की तरह लगता है, उसे जवाब देने का कोई अच्छा कारण नहीं है कि उसे खुद को समझना चाहिए। मेरे पास विश्वविद्यालय के काम से सबसे इष्टतम हैप्रिम कार्यान्वयन है, लेकिन मुझे जवाब पोस्ट करके कोई अच्छा आना नहीं दिखता है, इसलिए वह इसे कॉपी कर सकता है और सोच सकता है कि वह हास्केल में बहुत अच्छा है। 3) अपने जीवन को हल करें, कुछ गरिमा है। –

1

Landei के समाधान है:

isPrime x = null $ filter divisible $ takeWhile notTooBig [2..] where 
    divisible y = x `mod`y == 0 
    notTooBig y = y*y <= x 

आप इसे लगभग "मानव पठनीय" कर सकते हैं किसी भी $ नहीं के साथ अशक्त $ फिल्टर की जगह बढ़िया, हालांकि, यदि आप एक और अधिक कुशल कार्यान्वयन चाहते हैं तो हमारे पास (बीएमएफ़ के लिए धन्यवाद):

-- list of all primes 
primes :: [Integer] 
primes = sieve (2 : 3 : possible [1..]) where 
    sieve (p : xs) = p : sieve [x | x <- xs, x `mod` p > 0] 
    possible (x:xs) = 6*x-1 : 6*x+1 : possible xs 

isPrime :: Integer -> Bool 
isPrime n = shortCircuit || (not $ any divisible $ takeWhile inRangeOf primes) where 
    shortCircuit = elem n [2,3] || (n < 25 && ((n-1) `mod` 6 == 0 || (n+1) `mod` 6 == 0)) 
    divisible y = n `mod` y == 0 
    inRangeOf y = y * y <= n 

'दक्षता' f आता है निरंतर प्राइम्स का उपयोग रोम। ,

  1. हास्केल क्रम परिणाम इतने बाद आमंत्रण मूल्यांकन नहीं किया जाता
  2. यह तर्क टिप्पणी से संख्या की श्रेणी समाप्त कि sieve मूल्य केवल एक पुनरावर्ती तालिका है कैश सकता है: यह दो तरह से खोज को बेहतर बनाता है जहां का प्रमुख कहता है, सूची प्रमुख है, और इसे इसमें जोड़ती है। शेष सूचियों के लिए यदि कोई नंबर पहले से सूचीबद्ध सूची में पहले से ही कोई मान नहीं है तो इसके प्राइम possible सभी संभावित प्राइम्स की सूची है, क्योंकि सभी संभावित प्राइम फॉर्म 6 * के -1 या 6 में हैं * k-1 को छोड़कर 2 और 3 यही नियम shortCircuit के लिए लागू किया जाता है बहुत जल्दी गणना
  3. से बाहर

DF द्वारा जमानत फ़ुटनोट
¹ यह अभी भी प्राइम्स खोजने के लिए एक बहुत ही अक्षम तरीका है। ट्रायल डिवीजन का प्रयोग न करें अगर आपको कुछ हजारों से अधिक प्राइम्स की आवश्यकता है, तो इसके बजाय एक चाकू का उपयोग करें। hackage पर कई far moreefficient कार्यान्वयन हैं।

+0

isPrime के लिए काम करने के लिए शॉर्टक्रिकिट को हटा देना है। यह 25 से मेल खाता है, उदाहरण के लिए, जो प्रमुख नहीं है। इसे संकलित करने के लिए मुझे चारों ओर ब्रैकेट की आवश्यकता थी ($ कोई भी विभाजित $ नहीं, जबकि रेंजऑफ प्राइम्स में)। – rdrey

+0

उत्पादित प्राइम्स की संख्या में 'primes' के लिए कोड * वर्गवार * है। एराटोस्टेनेस की चलनी की सैद्धांतिक समय जटिलता 'ओ (एन * लॉग एन * लॉग (लॉग एन)) है,' एन' प्राइम्स में उत्पादित है। परीक्षण प्रभाग की सैद्धांतिक जटिलता 'ओ (एन^1.5/(लॉग एन)^0.5) 'है। फिर वह कोड, जो कि पर्याप्त परीक्षण परीक्षण सरल प्रतीत होता है, इतना बुरा करता है? ऐसा इसलिए है क्योंकि प्रत्येक फ़िल्टर * की फायरिंग *** *** स्थगित होनी चाहिए *** जब तक कि प्राइम स्क्वायर इनपुट स्ट्रीम में नहीं देखा जाता। इनपुट स्ट्रीम को तीसरे स्थान पर कम करने से निरंतर कारक कम हो जाता है, और कुछ भी नहीं। –