रेटिना , 66 63 45 43 36 बाइट्स
^()(\1(?<1>.\1))+(\1(.(?(4).\4)))*$
रेटिना के शीर्षक के बावजूद, यह केवल एक सादा .NET .NET रेगेक्स है जो लोसेचियन नंबरों के एकात्मक प्रतिनिधित्व को स्वीकार करता है ।
इनपुट्स 999 और 1000 एक सेकंड के तहत अच्छी तरह से लेते हैं।
इसे ऑनलाइन आज़माएं! (पहली पंक्ति एक लाइनफ़ीड-अलग किए गए परीक्षण सूट को सक्षम करती है, और अगले दो रूपांतरण सुविधाओं के लिए एकात्मकता का ख्याल रखते हैं।)
व्याख्या
समाधान वर्गीकरण पर आधारित है कि इनपुट को i*i + j*(i + j)सकारात्मक iऔर गैर-नकारात्मक j(चूंकि हमें इनपुट को संभालने की आवश्यकता नहीं है 0) के लिए लिखा जा सकता है , और n*nयह केवल पहले nविषम पूर्णांक का योग है । इसे आगे के संदर्भों में देखना एक दिलचस्प अभ्यास था।
एक "फॉरवर्ड रेफरेंस" तब होता है जब आप उस समूह के अंदर एक बैकरेसेंस रखते हैं जिसे वह संदर्भित करता है। बेशक, जब समूह पहली बार उपयोग किया जाता है, तो काम नहीं करता है, क्योंकि अभी तक बैकरेफ़र्ड होने के लिए कुछ भी नहीं है, लेकिन यदि आप इसे एक लूप में रखते हैं, तो बैकरेफेरेंस को पिछली बार पुनरावृत्ति प्राप्त होती है। यह बदले में, चलो आप प्रत्येक पुनरावृत्ति के साथ एक बड़ा कब्जा बनाते हैं। इसका उपयोग त्रिकोणीय संख्याओं, वर्गों और फाइबोनैचि संख्याओं जैसी चीजों के लिए बहुत कॉम्पैक्ट पैटर्न तैयार करने के लिए किया जा सकता है।
एक उदाहरण के रूप में, इस तथ्य का उपयोग करते हुए कि वर्ग पहले nविषम पूर्णांक के योग हैं, हम इस तरह एक वर्ग इनपुट से मेल कर सकते हैं:
(^.|..\1)+$
पहली यात्रा पर, ..\1काम नहीं कर सकते, क्योंकि \1अभी तक कोई मूल्य नहीं है। इसलिए हम ^.समूह में किसी एक वर्ण को कैप्चर करना शुरू करते हैं 1। बाद के पुनरावृत्तियों पर, ^.लंगर के कारण अब मेल नहीं खाता, लेकिन अब ..\1मान्य है। यह पिछले पुनरावृति की तुलना में दो अधिक वर्णों से मेल खाता है और कैप्चर को अद्यतन करता है। इस तरह हम बढ़ती संख्याओं से मेल खाते हैं, प्रत्येक पुनरावृत्ति के बाद एक वर्ग हो रहा है।
अब दुर्भाग्य से, हम इस तकनीक का उपयोग नहीं कर सकते हैं। मिलान करने के बाद i*i, हमें भी प्राप्त करने की आवश्यकता है i, ताकि हम इसे गुणा कर सकें j। ऐसा करने का एक सरल (लेकिन लंबा) तरीका इस तथ्य का उपयोग करना है कि मिलान पुनरावृत्तियों i*iलेता है i, ताकि हमने iसमूह में चीजों को पकड़ लिया है 1। अब हम इसे निकालने के लिए संतुलन समूहों का उपयोग कर सकते हैं i, लेकिन जैसे मैंने कहा कि यह महंगा है।
इसके बजाय, मैंने इस "लगातार विषम पूर्णांक का योग" लिखने के लिए एक अलग तरीका निकाला i, जो अंत में एक कैप्चरिंग समूह में भी पैदावार देता है। निश्चित ही iविषम संख्या बस है 2i-1। यह हमें प्रत्येक पुनरावृत्ति पर केवल 1 द्वारा आगे के संदर्भ को बढ़ाने का एक तरीका देता है। यह हिस्सा है:
^()(\1(?<1>.\1))+
यह ()सिर्फ समूह पर एक खाली कब्जा धक्का 1(initialising iलिए 0)। यह ^.|ऊपर दिए गए सरल समाधान में काफी समान है , लेकिन |इस मामले में उपयोग करना थोड़ा पेचीदा होगा।
फिर हमारे पास मुख्य लूप है (\1(?<1>.\1))। \1पहले से मेल खाता है i, (?<1>.\1)फिर समूह 1को अपडेट करता है i+1। नए के संदर्भ में i, हमने अभी-अभी 2i-1वर्णों का मिलान किया है। वास्तव में हमें जो चाहिए।
जब हम कर लेते हैं, तो हम कुछ वर्ग से मेल खाते हैं i*iऔर समूह में 1अभी भी iअक्षर हैं।
दूसरा भाग सरल वर्ग मिलान के करीब है जो मैंने ऊपर दिखाया था। चलो 1अब के लिए पीछे हटने की उपेक्षा करें :
(.(?(4).\1))*
यह मूल रूप से समान है (^.|..\4)*, सिवाय इसके कि हम उपयोग नहीं कर सकते ^क्योंकि हम स्ट्रिंग की शुरुआत में नहीं हैं। इसके बजाय हम एक सशर्त का उपयोग करते हैं, अतिरिक्त से मेल खाने के लिए .\1जब हम पहले ही समूह का उपयोग कर चुके होते हैं 4। लेकिन वास्तव में यह बिल्कुल वैसा ही है। यह हमें देता है j*j।
केवल एक चीज जो गायब है वह है j*iपद। हम इसे इस j*jतथ्य के उपयोग से जोड़ते हैं कि j*jगणना अभी भी jपुनरावृत्तियों को लेती है । इसलिए प्रत्येक यात्रा के लिए हम भी द्वारा कर्सर अग्रिम iके साथ \1। हमें केवल यह सुनिश्चित करने की आवश्यकता है कि इसे समूह में न लिखें 4, क्योंकि यह लगातार विषम संख्याओं के मिलान के साथ गड़बड़ करेगा। इस प्रकार हम यहां पहुंचे:
(\1(.(?(4).\1)))*