फंकिटॉन , गैर-प्रतिस्पर्धी
अद्यतन करें! बड़े पैमाने पर प्रदर्शन में सुधार! n = 7 अब 10 मिनट से कम समय में पूरा होता है! नीचे देखें स्पष्टीकरण!
यह लिखने में अच्छा लगा। फनसिटॉन में लिखी गई इस समस्या के लिए यह एक ब्रूट-फोर्स सॉल्वर है। कुछ तथ्य:
- यह STDIN पर पूर्णांक को स्वीकार करता है। कोई भी बाहरी व्हाट्सएप इसे पूर्णांक के बाद एक नई रेखा सहित तोड़ता है।
- यह संख्या 0 से n - 1 (1 से n नहीं ) का उपयोग करता है।
- यह ग्रिड को "पीछे की ओर" भरता है, इसलिए आपको एक समाधान मिलता है जहां नीचे की पंक्ति पढ़ती
3 2 1 0
है जहां शीर्ष पंक्ति पढ़ती है 0 1 2 3
।
- यह n = 1 के
0
लिए सही ढंग से आउटपुट (एकमात्र समाधान) है ।
- N = 2 और n = 3 के लिए खाली आउटपुट ।
- जब एक निर्वासन के लिए संकलित किया जाता है, तो n = 7 के लिए लगभग 8iled मिनट लगते हैं (प्रदर्शन में सुधार से एक घंटे पहले)। संकलित किए बिना (दुभाषिया का उपयोग करते हुए) इसे लगभग 1.5 गुना लंबा लगता है, इसलिए संकलक का उपयोग करना इसके लायक है।
- एक व्यक्तिगत मील के पत्थर के रूप में, यह पहली बार है जब मैंने एक छद्म भाषा में कार्यक्रम लिखने के बिना पूरे फनसिटॉन कार्यक्रम को लिखा। मैंने इसे वास्तविक C # पहली बार में लिखा था।
- (हालांकि, यह पहली बार नहीं है जब मैंने फ़नसिटॉन में किसी चीज़ के प्रदर्शन में बड़े पैमाने पर सुधार करने के लिए बदलाव किया है। पहली बार मैंने ऐसा किया था जो तथ्यात्मक कार्य में था। गुणन के संचालन के आदेश को स्वैप करने के कारण बहुत बड़ा बदलाव आया। कैसे गुणन एल्गोरिथ्म काम करता है । बस अगर आप उत्सुक थे।)
बिना और देरी के:
┌────────────────────────────────────┐ ┌─────────────────┐
│ ┌─┴─╖ ╓───╖ ┌─┴─╖ ┌──────┐ │
│ ┌─────────────┤ · ╟─╢ Ӂ ╟─┤ · ╟───┤ │ │
│ │ ╘═╤═╝ ╙─┬─╜ ╘═╤═╝ ┌─┴─╖ │ │
│ │ └─────┴─────┘ │ ♯ ║ │ │
│ ┌─┴─╖ ╘═╤═╝ │ │
│ ┌────────────┤ · ╟───────────────────────────────┴───┐ │ │
┌─┴─╖ ┌─┴─╖ ┌────╖ ╘═╤═╝ ┌──────────┐ ┌────────┐ ┌─┴─╖│ │
│ ♭ ║ │ × ╟───┤ >> ╟───┴───┘ ┌─┴─╖ │ ┌────╖ └─┤ · ╟┴┐ │
╘═╤═╝ ╘═╤═╝ ╘══╤═╝ ┌─────┤ · ╟───────┴─┤ << ╟─┐ ╘═╤═╝ │ │
┌───────┴─────┘ ┌────╖ │ │ ╘═╤═╝ ╘══╤═╝ │ │ │ │
│ ┌─────────┤ >> ╟─┘ │ └───────┐ │ │ │ │ │
│ │ ╘══╤═╝ ┌─┴─╖ ╔═══╗ ┌─┴─╖ ┌┐ │ │ ┌─┴─╖ │ │
│ │ ┌┴┐ ┌───────┤ ♫ ║ ┌─╢ 0 ║ ┌─┤ · ╟─┤├─┤ ├─┤ Ӝ ║ │ │
│ │ ╔═══╗ └┬┘ │ ╘═╤═╝ │ ╚═╤═╝ │ ╘═╤═╝ └┘ │ │ ╘═╤═╝ │ │
│ │ ║ 1 ╟───┬┘ ┌─┴─╖ └───┘ ┌─┴─╖ │ │ │ │ │ ┌─┴─╖ │
│ │ ╚═══╝ ┌─┴─╖ │ ɓ ╟─────────────┤ ? ╟─┘ │ ┌─┴─╖ │ ├─┤ · ╟─┴─┐
│ ├─────────┤ · ╟─┐ ╘═╤═╝ ╘═╤═╝ ┌─┴────┤ + ╟─┘ │ ╘═╤═╝ │
┌─┴─╖ ┌─┴─╖ ╘═╤═╝ │ ╔═╧═╕ ╔═══╗ ┌───╖ ┌─┴─╖ ┌─┴─╖ ╘═══╝ │ │ │
┌─┤ · ╟─┤ · ╟───┐ └┐ └─╢ ├─╢ 0 ╟─┤ ⌑ ╟─┤ ? ╟─┤ · ╟──────────────┘ │ │
│ ╘═╤═╝ ╘═╤═╝ └───┐ ┌┴┐ ╚═╤═╛ ╚═╤═╝ ╘═══╝ ╘═╤═╝ ╘═╤═╝ │ │
│ │ ┌─┴─╖ ┌───╖ │ └┬┘ ┌─┴─╖ ┌─┘ │ │ │ │
│ ┌─┴───┤ · ╟─┤ Җ ╟─┘ └────┤ ? ╟─┴─┐ ┌─────────────┘ │ │
│ │ ╘═╤═╝ ╘═╤═╝ ╘═╤═╝ │ │╔════╗╔════╗ │ │
│ │ │ ┌──┴─╖ ┌┐ ┌┐ ┌─┴─╖ ┌─┴─╖ │║ 10 ║║ 32 ║ ┌─────────────────┘ │
│ │ │ │ << ╟─┤├─┬─┤├─┤ · ╟─┤ · ╟─┘╚══╤═╝╚╤═══╝ ┌──┴──┐ │
│ │ │ ╘══╤═╝ └┘ │ └┘ ╘═╤═╝ ╘═╤═╝ │ ┌─┴─╖ ┌─┴─╖ ┌─┴─╖ │
│ │ ┌─┴─╖ ┌─┴─╖ ┌─┴─╖ ┌─┴─╖ ╔═╧═╕ └─┤ ? ╟─┤ · ╟─┤ % ║ │
│ └─────┤ · ╟─┤ · ╟──┤ Ӂ ╟──┤ ɱ ╟─╢ ├───┐ ╘═╤═╝ ╘═╤═╝ ╘═╤═╝ │
│ ╘═╤═╝ ╘═╤═╝ ╘═╤═╝ ╘═══╝ ╚═╤═╛ ┌─┴─╖ ┌─┴─╖ │ └────────────────────┘
│ └─────┤ │ └───┤ ‼ ╟─┤ ‼ ║ │ ┌──────┐
│ │ │ ╘═══╝ ╘═╤═╝ │ │ ┌────┴────╖
│ │ │ ┌─┴─╖ │ │ │ str→int ║
│ │ └──────────────────────┤ · ╟───┴─┐ │ ╘════╤════╝
│ │ ┌─────────╖ ╘═╤═╝ │ ╔═╧═╗ ┌──┴──┐
│ └──────────┤ int→str ╟──────────┘ │ ║ ║ │ ┌───┴───┐
│ ╘═════════╝ │ ╚═══╝ │ │ ┌───╖ │
└───────────────────────────────────────────────────────┘ │ └─┤ × ╟─┘
┌──────────────┐ ╔═══╗ │ ╘═╤═╝
╔════╗ │ ╓───╖ ┌───╖ │ ┌───╢ 0 ║ │ ┌─┴─╖ ╔═══╗
║ −1 ║ └─╢ Ӝ ╟─┤ × ╟──┴──────┐ │ ╚═╤═╝ └───┤ Ӂ ╟─╢ 0 ║
╚═╤══╝ ╙───╜ ╘═╤═╝ │ │ ┌─┴─╖ ╘═╤═╝ ╚═══╝
┌─┴──╖ ┌┐ ┌───╖ ┌┐ ┌─┴──╖ ╔════╗ │ │ ┌─┤ ╟───────┴───────┐
│ << ╟─┤├─┤ ÷ ╟─┤├─┤ << ║ ║ −1 ║ │ │ │ └─┬─╜ ┌─┐ ┌─────┐ │
╘═╤══╝ └┘ ╘═╤═╝ └┘ ╘═╤══╝ ╚═╤══╝ │ │ │ └───┴─┘ │ ┌─┴─╖ │
│ └─┘ └──────┘ │ │ └───────────┘ ┌─┤ ? ╟─┘
└──────────────────────────────┘ ╓───╖ └───────────────┘ ╘═╤═╝
┌───────────╢ Җ ╟────────────┐ │
┌────────────────────────┴───┐ ╙───╜ │
│ ┌─┴────────────────────┐ ┌─┴─╖
┌─┴─╖ ┌─┴─╖ ┌─┴─┤ · ╟──────────────────┐
│ ♯ ║ ┌────────────────────┤ · ╟───────┐ │ ╘═╤═╝ │
╘═╤═╝ │ ╘═╤═╝ │ │ │ ┌───╖ │
┌─────┴───┘ ┌─────────────────┴─┐ ┌───┴───┐ ┌─┴─╖ ┌─┴─╖ ┌─┤ × ╟─┴─┐
│ │ ┌─┴─╖ │ ┌───┴────┤ · ╟─┤ · ╟──────────┤ ╘═╤═╝ │
│ │ ┌───╖ ┌───╖ ┌──┤ · ╟─┘ ┌─┴─┐ ╘═╤═╝ ╘═╤═╝ ┌─┴─╖ │ │
│ ┌────┴─┤ ♭ ╟─┤ × ╟──┘ ╘═╤═╝ │ ┌─┴─╖ ┌───╖└┐ ┌──┴─╖ ┌─┤ · ╟─┘ │
│ │ ╘═══╝ ╘═╤═╝ ┌───╖ │ │ │ × ╟─┤ Ӝ ╟─┴─┤ ÷% ╟─┐ │ ╘═╤═╝ ┌───╖ │
│ ┌─────┴───┐ ┌────┴───┤ Ӝ ╟─┴─┐ │ ╘═╤═╝ ╘═╤═╝ ╘══╤═╝ │ │ └───┤ Ӝ ╟─┘
│ ┌─┴─╖ ┌───╖ │ │ ┌────╖ ╘═╤═╝ │ └───┘ ┌─┴─╖ │ │ └────┐ ╘═╤═╝
│ │ × ╟─┤ Ӝ ╟─┘ └─┤ << ╟───┘ ┌─┴─╖ ┌───────┤ · ╟───┐ │ ┌─┴─╖ ┌───╖ │ │
│ ╘═╤═╝ ╘═╤═╝ ╘══╤═╝ ┌───┤ + ║ │ ╘═╤═╝ ├──┴─┤ · ╟─┤ × ╟─┘ │
└───┤ └────┐ ╔═══╗ ┌─┴─╖ ┌─┴─╖ ╘═╤═╝ │ ╔═══╗ ┌─┴─╖ ┌─┴─╖ ╘═╤═╝ ╘═╤═╝ │
┌─┴─╖ ┌────╖ │ ║ 0 ╟─┤ ? ╟─┤ = ║ ┌┴┐ │ ║ 0 ╟─┤ ? ╟─┤ = ║ │ │ ┌────╖ │
│ × ╟─┤ << ╟─┘ ╚═══╝ ╘═╤═╝ ╘═╤═╝ └┬┘ │ ╚═══╝ ╘═╤═╝ ╘═╤═╝ │ └─┤ << ╟─┘
╘═╤═╝ ╘═╤══╝ ┌┐ ┌┐ │ │ └───┘ ┌─┴─╖ ├──────┘ ╘═╤══╝
│ └────┤├──┬──┤├─┘ ├─────────────────┤ · ╟───┘ │
│ └┘┌─┴─╖└┘ │ ┌┐ ┌┐ ╘═╤═╝ ┌┐ ┌┐ │
└────────────┤ · ╟─────────┘ ┌─┤├─┬─┤├─┐ └───┤├─┬─┤├────────────┘
╘═╤═╝ │ └┘ │ └┘ │ └┘ │ └┘
└───────────────┘ │ └────────────┘
पहले संस्करण की व्याख्या
N = 7. को हल करने के लिए पहले संस्करण में लगभग एक घंटे का समय लगा । निम्न में से ज्यादातर बताते हैं कि इस धीमे संस्करण ने कैसे काम किया। नीचे मैं बताऊंगा कि मैंने 10 मिनट से कम समय में इसे बनाने के लिए क्या बदलाव किया।
बिट्स में एक भ्रमण
इस कार्यक्रम को बिट्स की जरूरत है। इसे बहुत सारे बिट्स की आवश्यकता होती है, और इसे सभी सही स्थानों पर उनकी आवश्यकता होती है। अनुभवी Funciton प्रोग्रामर पहले से ही जानते हैं कि यदि आपको n बिट्स की आवश्यकता है , तो आप सूत्र का उपयोग कर सकते हैं
जिसे फंटिसटन में व्यक्त किया जा सकता है
मेरे प्रदर्शन का अनुकूलन करते समय, मेरे साथ यह हुआ कि मैं इस सूत्र का उपयोग करके समान मूल्य की बहुत तेज़ी से गणना कर सकता हूं:
मुझे आशा है कि आप मुझे क्षमा करेंगे कि मैंने इस पोस्ट में सभी समीकरण ग्राफिक्स को तदनुसार अपडेट नहीं किया।
अब, मान लें कि आप बिट्स का एक सन्निहित ब्लॉक नहीं चाहते हैं; वास्तव में, आप चाहते हैं कि नियमित अंतराल पर n बिट्स हर k -th बिट की तरह हों, जैसे:
LSB
↓
00000010000001000000100000010000001
└──┬──┘
k
यह जानने के बाद इसके लिए सूत्र काफी सीधा-सीधा है:
कोड में, फ़ंक्शन n और kӜ
मान लेता है और इस सूत्र की गणना करता है।
उपयोग किए गए नंबरों का ट्रैक रखना
अंतिम ग्रिड में n are संख्याएँ हैं, और प्रत्येक संख्या n संभव मानों में से कोई भी हो सकती है। प्रत्येक सेल में किस संख्या की अनुमति है, इस पर नज़र रखने के लिए, हम n keep बिट्स से मिलकर एक संख्या बनाए रखते हैं , जिसमें यह दर्शाने के लिए एक बिट सेट किया जाता है कि एक विशेष मान लिया गया है। प्रारंभ में यह संख्या 0 है, जाहिर है।
एल्गोरिथ्म नीचे-दाएं कोने में शुरू होता है। "अनुमान लगाने" के बाद पहली संख्या 0 है, हमें इस तथ्य पर नज़र रखने की आवश्यकता है कि 0 को अब किसी पंक्ति, स्तंभ और विकर्ण के साथ किसी भी सेल में अनुमति नहीं है:
LSB (example n=5)
↓
10000 00000 00000 00000 10000
00000 10000 00000 00000 10000
00000 00000 10000 00000 10000
00000 00000 00000 10000 10000
10000 10000 10000 10000 10000
↑
MSB
इसके लिए, हम निम्नलिखित चार मानों की गणना करते हैं:
वर्तमान पंक्ति: हमें प्रत्येक n- बिट बिट (एक सेल) में n बिट्स की आवश्यकता है , और फिर इसे वर्तमान पंक्ति r पर स्थानांतरित करें , याद रखें कि प्रत्येक पंक्ति में n : बिट्स हैं:
वर्तमान स्तंभ: हम की जरूरत n हर बिट्स n ²-वें बिट (प्रति पंक्ति एक), और फिर वर्तमान स्तंभ के लिए यह बदलाव ग , हर स्तंभ याद शामिल n बिट्स:
फॉरवर्ड विकर्ण: हमें हर बिट n की आवश्यकता है ... (क्या आपने ध्यान दिया? त्वरित, यह पता लगाओ!) ... n ( n +1) -थ बिट (अच्छा किया!), लेकिन केवल अगर हम वास्तव में हैं। आगे विकर्ण:
बैकवर्ड विकर्ण: यहां दो चीजें। सबसे पहले, हम कैसे जानते हैं कि हम पिछड़े विकर्ण पर हैं? गणितीय रूप से, स्थिति c = ( n - 1) - r है , जो कि c = n + (- r - 1) के समान है। अरे, क्या यह आपको कुछ याद दिलाता है? यह सही है, यह दो का पूरक है, इसलिए हम डिक्रिप्ट के बजाय बिटवाइज़ निगेटिव (फ़नसिटॉन में बहुत कुशल) का उपयोग कर सकते हैं। दूसरा, ऊपर दिया गया सूत्र मानता है कि हम चाहते हैं कि कम से कम महत्वपूर्ण बिट सेट किया जाए, लेकिन पिछड़े विकर्ण में हम नहीं करते हैं, इसलिए हमें इसे ऊपर स्थानांतरित करना होगा ... क्या आप जानते हैं? ... यह सही है, एन ( एन - 1)।
यह भी केवल एक ही है जहाँ हम संभावित रूप से 0 से विभाजित करते हैं यदि n = 1. हालाँकि, फ़नसिटॉन परवाह नहीं करता है। 0 0 0 सिर्फ 0 है, क्या आप नहीं जानते?
कोड में, फ़ंक्शन Җ
(नीचे वाला) n और एक सूचकांक लेता है (जिसमें से यह विभाजन और शेष द्वारा आर और सी की गणना करता है), इन चार मूल्यों की गणना करता है और or
उन्हें एक साथ जोड़ता है।
जानवर बल एल्गोरिथ्म
जानवर-बल एल्गोरिथ्म Ӂ
(शीर्ष पर फ़ंक्शन) द्वारा कार्यान्वित किया जाता है । यह n (ग्रिड आकार), अनुक्रमणिका (जहां ग्रिड में हम वर्तमान में एक संख्या रख रहे हैं ) लेता है , और लिया ( n ³ बिट्स के साथ संख्या हमें बताती है कि हम प्रत्येक कक्ष में अभी भी कौन से नंबर रख सकते हैं)।
यह फ़ंक्शन स्ट्रिंग्स का एक क्रम देता है। प्रत्येक स्ट्रिंग ग्रिड का पूर्ण समाधान है। यह एक पूर्ण विलेय है; यदि आप इसे छोड़ देते हैं तो यह सभी समाधान लौटा देगा, लेकिन यह उन्हें एक आलसी-मूल्यांकित अनुक्रम के रूप में लौटाता है।
यदि इंडेक्स 0 पर पहुंच गया है, तो हमने पूरी ग्रिड को सफलतापूर्वक भर दिया है, इसलिए हम एक अनुक्रम देते हैं जिसमें खाली स्ट्रिंग (एक एकल समाधान जो कोशिकाओं में से किसी को भी शामिल नहीं करता है) है। खाली स्ट्रिंग है 0
, और हम लाइब्रेरी फंक्शन ⌑
का उपयोग करते हैं जो कि सिंगल-एलिमेंट सीक्वेंस में बदल जाता है।
नीचे प्रदर्शन सुधार के तहत वर्णित चेक यहां होता है।
यदि इंडेक्स अभी तक 0 तक नहीं पहुंचा है, तो हम इंडेक्स प्राप्त करने के लिए इसे 1 से घटाते हैं, जिस पर अब हमें एक नंबर (कॉल करने के लिए ix ) चाहिए।
हम ♫
0 से n - 1 तक के मानों वाले एक आलसी अनुक्रम उत्पन्न करने के लिए उपयोग करते हैं ।
फिर हम ɓ
एक मेमने के साथ (मोनैडिक बाइंड) का उपयोग करते हैं जो निम्न क्रम में करता है:
- में प्रासंगिक बिट पर सबसे पहले नज़र लिया तय करने के लिए संख्या यहां हों या मान्य है या नहीं। हम एक संख्या जगह कर सकते मैं अगर और सिर्फ़ अगर ले लिया और (1 << ( n × ix ) << मैं ) पहले से ही सेट नहीं है। यदि यह सेट है, तो वापस लौटें
0
(खाली अनुक्रम)।
Җ
वर्तमान पंक्ति, स्तंभ और विकर्ण (ओं) के अनुरूप बिट्स की गणना करने के लिए उपयोग करें । मैं इसे द्वारा स्थानांतरित कर दिया और फिर or
इसे ले लिया ।
Ӂ
शेष कोशिकाओं के लिए सभी समाधानों को पुनः प्राप्त करने के लिए पुनरावर्ती कॉल करें , इसे नया लिया गया और निस्तारण ix । यह अधूरे तारों का एक क्रम देता है; प्रत्येक स्ट्रिंग में ix वर्ण (अनुक्रमणिका ix तक भरा ग्रिड ) होता है।
- का प्रयोग करें
ɱ
(नक्शा) समाधान thusly पाया के माध्यम से जाने और प्रयोग करने में ‼
श्रेणीबद्ध करने के लिए मैं प्रत्येक के अंत करने के लिए। यदि अनुक्रमणिका n के एक से अधिक है , तो एक नई पंक्ति में जोड़ें , अन्यथा एक स्थान।
परिणाम उत्पन्न करना
N , index = n remember (याद रखें कि हम ग्रिड को पीछे से भरते हैं) और लिया = (शुरुआत में कुछ भी नहीं लिया गया है) के Ӂ
साथ मुख्य प्रोग्राम कॉल (ब्रूट फॉरेसर )। यदि इसका परिणाम एक खाली अनुक्रम है (कोई समाधान नहीं मिला), तो रिक्त स्ट्रिंग को आउटपुट करें। अन्यथा, पहले स्ट्रिंग को अनुक्रम में आउटपुट करें। ध्यान दें कि इसका मतलब है कि यह अनुक्रम के पहले तत्व का मूल्यांकन करेगा, यही कारण है कि सॉल्वर तब तक जारी नहीं होता है जब तक कि यह सभी समाधान नहीं मिला है।
प्रदर्शन में सुधार
(उन लोगों के लिए जो पहले से ही स्पष्टीकरण के पुराने संस्करण को पढ़ते हैं: कार्यक्रम अब अनुक्रमों के अनुक्रम को उत्पन्न नहीं करता है जिन्हें अलग से आउटपुट के लिए एक स्ट्रिंग में बदलने की आवश्यकता होती है; यह सीधे तार के अनुक्रम को उत्पन्न करता है। मैंने तदनुसार स्पष्टीकरण संपादित किया है। लेकिन यह मुख्य सुधार नहीं था। यहाँ यह आता है।]
मेरी मशीन पर, पहले संस्करण के संकलित निर्गमन को n = 7. हल करने में बहुत अधिक ठीक 1 घंटा लगता था। यह 10 मिनट की दी गई समय सीमा के भीतर नहीं था, इसलिए मैंने आराम नहीं किया। (ठीक है, वास्तव में, कारण कि मैं आराम नहीं करता था, क्योंकि मुझे यह विचार था कि इसे बड़े पैमाने पर कैसे गति दें।)
जैसा कि ऊपर वर्णित एल्गोरिथ्म इसकी खोज को रोक देता है और हर बार यह एक सेल का सामना करता है जिसमें लेई गई संख्या में सभी बिट्स सेट होते हैं, यह दर्शाता है कि इस सेल में कुछ भी नहीं डाला जा सकता है।
हालांकि, एल्गोरिथ्म जारी रहेगा क्षुद्रता के साथ ग्रिड को भरने के लिए अप करने के लिए सेल, जिसमें उन सभी बिट्स सेट कर रहे हैं। यह बहुत तेजी से होगा अगर यह किसी भी अभी तक भरे-से-भरे सेल के रूप में जल्द से जल्द बंद हो सकता है , जिसमें पहले से ही सभी बिट्स सेट हैं, जो पहले से ही इंगित करता है कि हम बाकी ग्रिड को कभी भी हल नहीं कर सकते हैं चाहे हम कितनी भी संख्या में डाल दें। यह। लेकिन आप कैसे कुशलता से जांचते हैं कि क्या किसी भी सेल ने अपने एन बिट्स को उन सभी के माध्यम से जाने के बिना सेट किया है?
ली गई संख्या में प्रति सेल एक बिट जोड़ने से चाल शुरू होती है । इसके बजाय जो ऊपर दिखाया गया था, वह अब इस तरह दिखता है:
LSB (example n=5)
↓
10000 0 00000 0 00000 0 00000 0 10000 0
00000 0 10000 0 00000 0 00000 0 10000 0
00000 0 00000 0 10000 0 00000 0 10000 0
00000 0 00000 0 00000 0 10000 0 10000 0
10000 0 10000 0 10000 0 10000 0 10000 0
↑
MSB
के बजाय n ³, वहाँ अब कर रहे हैं n ² ( n + 1) इस संख्या में बिट्स। वर्तमान पंक्ति / स्तंभ / विकर्ण को पॉपुलेट करने वाले फ़ंक्शन को तदनुसार बदल दिया गया है (वास्तव में, पूरी तरह से ईमानदार होने के लिए फिर से लिखा गया)। यह फ़ंक्शन अभी भी प्रति सेल केवल n बिट्स को आबाद करेगा , इसलिए हमने जो अतिरिक्त बिट जोड़ा है वह हमेशा रहेगा 0
।
अब, मान लें कि हम गणना के माध्यम से आधे रास्ते पर हैं, हमने सिर्फ एक 1
को मध्य सेल में रखा है , और लिया गया नंबर कुछ इस तरह दिखता है:
current
LSB column (example n=5)
↓ ↓
11111 0 10010 0 01101 0 11100 0 11101 0
00011 0 11110 0 01101 0 11101 0 11100 0
11111 0 11110 0[11101 0]11100 0 11100 0 ← current row
11111 0 11111 0 11111 0 11111 0 11111 0
11111 0 11111 0 11111 0 11111 0 11111 0
↑
MSB
जैसा कि आप देख सकते हैं, टॉप-लेफ्ट सेल (इंडेक्स 0) और मिडिल-लेफ्ट सेल (इंडेक्स 10) अब असंभव हैं। हम इसे सबसे कुशलता से कैसे निर्धारित करते हैं?
एक संख्या पर विचार करें जिसमें प्रत्येक सेल का 0 वां बिट सेट किया गया है, लेकिन केवल वर्तमान सूचकांक तक। इस तरह की संख्या परिचित सूत्र का उपयोग करके गणना करना आसान है:
यदि हम इन दो संख्याओं को एक साथ जोड़ दें तो हमें क्या मिलेगा?
LSB LSB
↓ ↓
11111 0 10010 0 01101 0 11100 0 11101 0 10000 0 10000 0 10000 0 10000 0 10000 0 ╓───╖
00011 0 11110 0 01101 0 11101 0 11100 0 ║ 10000 0 10000 0 10000 0 10000 0 10000 0 ║
11111 0 11110 0 11101 0 11100 0 11100 0 ═══╬═══ 10000 0 10000 0 00000 0 00000 0 00000 0 ═════ ╓─╜
11111 0 11111 0 11111 0 11111 0 11111 0 ║ 00000 0 00000 0 00000 0 00000 0 00000 0 ═════ ╨
11111 0 11111 0 11111 0 11111 0 11111 0 00000 0 00000 0 00000 0 00000 0 00000 0 o
↑ ↑
MSB MSB
परिणाम है:
OMG
↓
00000[1]01010 0 11101 0 00010 0 00011 0
10011 0 00001 0 11101 0 00011 0 00010 0
═════ 00000[1]00001 0 00011 0 11100 0 11100 0
═════ 11111 0 11111 0 11111 0 11111 0 11111 0
11111 0 11111 0 11111 0 11111 0 11111 0
जैसा कि आप देख सकते हैं, जो अतिरिक्त बिट में जोड़ता है, जो हमने जोड़ा है, लेकिन केवल अगर उस सेल के लिए सभी बिट्स सेट हैं! इसलिए, जो कुछ करना बाकी है, वह उन बिट्स (ऊपर सूत्र के रूप में, लेकिन << n ) को बाहर निकालने के लिए है और यदि परिणाम 0 है तो जांच करें:
00000[1]01010 0 11101 0 00010 0 00011 0 ╓╖ 00000 1 00000 1 00000 1 00000 1 00000 1 ╓─╖ ╓───╖
10011 0 00001 0 11101 0 00011 0 00010 0 ╓╜╙╖ 00000 1 00000 1 00000 1 00000 1 00000 1 ╓╜ ╙╖ ║
00000[1]00001 0 00011 0 11100 0 11100 0 ╙╥╥╜ 00000 1 00000 1 00000 0 00000 0 00000 0 ═════ ║ ║ ╓─╜
11111 0 11111 0 11111 0 11111 0 11111 0 ╓╜╙╥╜ 00000 0 00000 0 00000 0 00000 0 00000 0 ═════ ╙╖ ╓╜ ╨
11111 0 11111 0 11111 0 11111 0 11111 0 ╙──╨─ 00000 0 00000 0 00000 0 00000 0 00000 0 ╙─╜ o
यदि यह शून्य नहीं है, तो ग्रिड असंभव है और हम रोक सकते हैं।
- समाधान दिखाने का स्क्रीनशॉट और n = 4 से 7 केलिए समय चल रहा है।