मुझे RosettaCode पर जावा के लिए निम्नलिखित कोड का उदाहरण मिला:
public static boolean prime(int n) { return !new String(new char[n]).matches(".?|(..+?)\\1+"); }
कैसे करता है .?|(..+?)\\1+
प्रधान संख्याओं को .?|(..+?)\\1+
?
आपने कहा है कि आप इस हिस्से को समझते हैं, लेकिन सिर्फ जोर देने के लिए, उत्पन्न स्ट्रिंग की आपूर्ति की गई संख्या के बराबर लंबाई है इसलिए स्ट्रिंग में तीन वर्ण हैं और यदि केवल n == 3
.?
रेगेक्स का पहला भाग कहते हैं, "कोई भी चरित्र, शून्य या एक बार" तो मूल रूप से, शून्य या एक अक्षर है – या, मैं जो ऊपर वर्णित है, n == 0 || n == 1
n == 0 || n == 1
यदि हमारे पास मैच है, तो उसके बदले में वापसी करें यह इस तथ्य से मेल खाती है कि शून्य और कोई प्रधान नहीं है
(..+?)\\1+
रेगेक्स का दूसरा हिस्सा एक छोटे पेचीदा है, जो समूह और बैक्रेरेन्ड्स पर निर्भर है। एक समूह कोष्ठकों में कुछ भी है, जिसे बाद में उपयोग के लिए फिर से कब्जा कर लिया जाता है और फिर regex इंजन द्वारा संग्रहीत किया जाता है। एक backreference एक मिलान समूह है जो बाद में एक ही regex में प्रयोग किया जाता है।
समूह 1 चरित्र को कब्जा करता है, फिर 1 या अधिक किसी भी वर्ण का। (+ चरित्र का मतलब है एक या अधिक, लेकिन केवल पिछले वर्ण या समूह का। तो यह "दो या चार या छह आदि वर्ण" नहीं है, बल्कि "दो या तीन इत्यादि" + + जैसा है +, लेकिन यह संभव के रूप में कुछ अक्षर के रूप में मिलान करने की कोशिश करता है। सामान्य रूप से पूरे स्ट्रिंग को झुकने की कोशिश करता है, यदि यह हो सकता है, जो इस मामले में खराब है क्योंकि यह बैक्रेफरेंस भाग को काम से रोकता है।)
अगला भाग बैक्रेफरेंस है: उस वही अक्षर का सेट (दो या अधिक), फिर से दिख रहा है। ने कहा कि बैक्रेफरेंस एक या अधिक बार दिखाई देता है।
इसलिए। कब्जा कर लिया गया समूह पात्रों की एक प्राकृतिक संख्या (2 आगे) से कब्जा कर लिया है समूह ने कहा कि तब कुछ प्राकृतिक संख्या दिखाई देती है (2 से आगे भी)। यदि कोई मैच है, तो इसका अर्थ है कि दो से अधिक संख्याओं के उत्पाद को खोजना संभव है जो 2 से अधिक या उसके बराबर है जो एन-लम्बाई स्ट्रिंग से मेल खाता है … अर्थ है कि आपके पास समग्र एन है तो फिर, सफल मैच का नकारा वापस लौटाएं: n प्राइम नहीं है
अगर कोई मैच नहीं मिला, तो आप दो प्राकृतिक संख्याओं के अपने उत्पाद के साथ नहीं आ सकते हैं जो कि 2 से अधिक या उसके बराबर है … और आपके पास एक गैर-मैच और एक प्रधान दोनों है, इसलिए फिर से अस्वीकृति की वापसी मैच परिणाम का
क्या आप इसे अब देख रहे हैं? यह अविश्वसनीय रूप से मुश्किल है (और कम्प्यूटेशनलली महंगे!), लेकिन एक बार जब आप इसे प्राप्त करते हैं, तब भी यह एक तरह से सरल होता है। 🙂
अगर आपके पास और प्रश्न हैं, तो मैं विस्तृत कर सकता हूं, जैसे रीजक्स पार्सिंग वास्तव में कैसे काम करता है। लेकिन मैं इस उत्तर को अब तक सरल रखने की कोशिश कर रहा हूं (या जितना आसान हो सकता है)।
मैं प्राइमलिटी टेस्टिंग के बाहर रेगेक्स भाग समझाऊंगा: निम्नलिखित रेगेक्स, String s
जो String t
को दोहराते हुए देखते हैं, उसे ढूंढता t
।
System.out.println( "MamamiaMamamiaMamamia".replaceAll("^(.*)\\1+$", "$1") ); // prints "Mamamia"
जिस तरह से यह काम करता है वह है कि regex को (.*)
\1
(.*)
में कैप्चर करता है (.*)
, और फिर देखता है कि इसके बाद का \1+
^
और $
का उपयोग सुनिश्चित करता है कि एक मैच पूरे स्ट्रिंग का होना चाहिए।
तो, एक तरह से, हमें String s
दिया जाता है, जो String t
का "मल्टीपल" होता String t
, और regex ऐसे t
पाएंगे (सबसे लंबे समय तक संभव है, क्योंकि \1
लालची है)।
एक बार जब आप समझते हैं कि यह रीजेक्स क्यों काम करता है, तो (अब ओपी के रेजेक्स में पहले वैकल्पिक की अनदेखी कर), समझाएं कि प्राइमलिटी परीक्षण के लिए इसका उपयोग कैसे किया जाता है
n
मूलभूतता का परीक्षण करने के लिए, पहले String
की लम्बाई n
बनाएं (एक ही char
से भरा) String
( k
) को \1
में लेता है, और शेष String
लिए \1+
से मिलान करने का प्रयास करता है
n
k
का एक उचित k
, और इसलिए n
प्राइम नहीं है। n
विभाजित करता है, और n
इसलिए एक प्रमुख है कैसे करता है
.?|(..+?)\1+
प्रधान संख्याओं को.?|(..+?)\1+
?
दरअसल, यह नहीं है! यह String
मेल खाता है जिसका लम्बाई प्रधानमंत्री नहीं है!
.?
: प्रत्यावर्तन का पहला भाग String
की लंबाई 0
या 1
(परिभाषा के अनुसार प्रधान नहीं है) (..+?)\1+
: प्रत्यावर्तन का दूसरा भाग, ऊपर वर्णित रीगेक्स की एक भिन्नता, लंबाई के String
से मेल खाता है जो कि String
की लंबाई " k >= 2
(अर्थात n
एक है समग्र, नहीं एक प्रमुख)।
?
वास्तव में शुद्धता के लिए आवश्यक नहीं है, लेकिन यह छोटी k
पहली कोशिश करके प्रक्रिया को तेज करने में मदद कर सकता है ध्यान दें !
return
वक्तव्य में boolean
पूरक ऑपरेटर: यह matches
नकार देता है यह तब होता है जब regex मेल नहीं खाता है, n
प्रधान है! यह एक डबल-नकारात्मक तर्क है, इसलिए कोई आश्चर्य नहीं कि यह भ्रामक है !!
इसे और अधिक पठनीय बनाने के लिए कोड का एक सरल पुन: लिखना यहां दिया गया है:
public static boolean isPrime(int n) { String lengthN = new String(new char[n]); boolean isNotPrimeN = lengthN.matches(".?|(..+?)\\1+"); return !isNotPrimeN; }
उपरोक्त अनिवार्यतः मूल जावा कोड के समान है, लेकिन तर्क को आसान समझने के लिए स्थानीय चर के असाइनमेंट के साथ कई बयानों में अलग हो गया है।
हम रेगएक्स को सरलीकृत पुनरावृत्ति का उपयोग करके भी सरल कर सकते हैं, निम्नानुसार:
boolean isNotPrimeN = lengthN.matches(".{0,1}|(.{2,})\\1+");
फिर, एक String
की लम्बाई दी, जो एक ही char
से भरी होती है,
.{0,1}
जांचता है कि n = 0,1
, नहीं प्रधानमंत्री (.{2,})\1+
चेक अगर n
एक के बराबर है k >= 2
, नहीं प्रधानमंत्री अनिच्छुक संशोधक के अपवाद के साथ ?
पर \1
(स्पष्टता के लिए छोड़े गए), उपरोक्त regex मूल के समान है।
निम्नलिखित regex समान तकनीक का उपयोग करता है; यह शैक्षिक होना चाहिए:
System.out.println( "OhMyGod=MyMyMyOhGodOhGodOhGod" .replaceAll("^(.+)(.+)(.+)=(\\1|\\2|\\3)+$", "$1! $2! $3!") ); // prints "Oh! My! God!"
अच्छा रेगेक्स चाल (हालांकि बहुत अक्षम) … 🙂
रेगेक्स गैर-प्राइम को निम्नानुसार परिभाषित करता है:
एन प्रधान नहीं है अगर और केवल अगर एन <= 1 या एन कुछ के द्वारा विभाज्य है> 1
रेगेक्स इंजन को एन के सरल डिजिटल प्रस्तुति को पारित करने के बजाय, यह लम्बाई एन के एक अनुक्रम से खिलाया जाता है, जिसमें दोहराए जाने वाले चरित्र का निर्माण होता है। N = 0 या N = 1 के लिए विच्छेदन की जांच का पहला भाग, और दूसरा, बैकरेरिएंट्स का उपयोग करके एक विभाजक के> 1 के लिए दिखता है। यह regex इंजन को कुछ गैर खाली उप-अनुक्रम को खोजने के लिए मजबूर करता है जिसे अनुक्रम बनाने के लिए कम-से-कम दो बार दोहराया जा सकता है। यदि इस तरह के बदलाव की मौजूदगी है, तो इसका मतलब है कि इसकी लंबाई एन को विभाजित करती है, इसलिए एन प्रधान नहीं है
/^1?$|^(11+?)\1+$/
आधार 1 (1 = 1, 2 = 11, 3 = 111, …) में रूपांतरण के बाद नंबर पर लागू करें। गैर-प्राइम इस से मेल खाएंगे। यदि यह मेल नहीं खाता है, तो यह प्रमुख है।
स्पष्टीकरण यहाँ ।