x86-64 मशीन कोड, 22 बाइट्स
48 B8 41 92 34 6D DB F7 FF FF 83 F9 40 7D 03 48 D3 E8 83 E0 01 C3
उपरोक्त बाइट्स 64-बिट x86 मशीन कोड में एक फ़ंक्शन को परिभाषित करता है जो यह निर्धारित करता है कि इनपुट मूल्य एक चिकन मैकगैग नंबर है या नहीं। विंडोज पर उपयोग किए जाने ECX
वाले Microsoft 64-बिट कॉलिंग कन्वेंशन के बाद, रजिस्टर में एकल पॉजिटिव पूर्णांक पैरामीटर पारित किया गया है। परिणाम EAX
रजिस्टर में लौटाया गया बूलियन मान है ।
असेंबली असेंबली mnemonics:
; bool IsMcNuggetNumber(int n)
; n is passed in ECX
movabs rax, 0xFFFFF7DB6D349241 ; load a 64-bit constant (the bit field)
cmp ecx, 64
jge TheEnd ; if input value >= 64, branch to end
shr rax, cl
TheEnd:
and eax, 1 ; mask off all but LSB
ret
जाहिर है, यह पायथन में एंडर्स कसेगोर के समाधान से बहुत अधिक खेलता है, जिसमें यह उन बिट-फ़ील्ड के आसपास है जो उन मूल्यों का प्रतिनिधित्व करते हैं जो चिकन मैकगैग नंबर हैं। विशेष रूप से, इस क्षेत्र में प्रत्येक बिट जो एक मान्य चिकन McNugget संख्या से मेल खाती है, 1 पर सेट है; अन्य सभी बिट्स 0 पर सेट हैं। (यह 0 को एक मान्य चिकन मैकगैग नंबर मानता है, लेकिन यदि आपको यह पसंद नहीं है, तो आपकी वरीयता एकल-बिट संशोधन है।)
हम इस मूल्य को रजिस्टर में लोड करके शुरू करते हैं। यह 64-बिट मान है, जो पहले से ही 8 बाइट्स को सांकेतिक शब्दों में बदलना है, इसके अलावा हमें एक-बाइट REX.W उपसर्ग की आवश्यकता है, इसलिए हम वास्तव में बाइट्स के मामले में काफी खर्च किए जा रहे हैं, लेकिन यह समाधान का दिल है, इसलिए मुझे लगता है कि यह इसके लायक है।
हम फिर इनपुट वैल्यू द्वारा फील्ड को राइट शिफ्ट करते हैं। * अंत में, हम सभी को छोड़ देते हैं, लेकिन सबसे कम-क्रम बिट, और यही हमारा बूलियन परिणाम बन जाता है।
हालाँकि, चूंकि आप वास्तव में मूल्य में बिट्स की संख्या से अधिक द्वारा स्थानांतरित नहीं कर सकते हैं, यह केवल ०-६३ से इनपुट के लिए काम करता है। उच्च इनपुट मानों का समर्थन करने के लिए, हम फ़ंक्शन के शीर्ष पर एक परीक्षण सम्मिलित करते हैं, जो कि इनपुट वैल्यू के निचले भाग की शाखाएँ> = 64 हैं। इसके बारे में केवल एक ही बात दिलचस्प है कि हम बिट-फ़ील्ड को लगातार और फिर शाखा में लोड करते हैं RAX
उस निर्देश के नीचे, जो सबसे कम-क्रम बिट से मास्क करता है, इस प्रकार यह सुनिश्चित करता है कि हम हमेशा 1 लौटें।
इसे ऑनलाइन आज़माएं!
(C फ़ंक्शन कॉल को एक विशेषता के साथ एनोटेट किया गया है, जो GCC को Microsoft कॉलिंग कन्वेंशन का उपयोग करके कॉल करने का कारण है जो कि एक असेंबली कोड का उपयोग करता है। यदि TIO ने MSVC प्रदान किया था, तो यह आवश्यक नहीं होगा।)
__
* एक पारी के विकल्प के रूप में, हम x86 BT
निर्देश का उपयोग कर सकते थे , लेकिन यह 1 बाइट को सांकेतिक शब्दों में बदलना है, इसलिए कोई फायदा नहीं हुआ। जब तक हमें एक अलग कॉलिंग कन्वेंशन का उपयोग करने के लिए मजबूर किया गया था जो ECX
रजिस्टर में इनपुट मूल्य को आसानी से पारित नहीं करता था । यह एक समस्या होगी, क्योंकि SHR
आवश्यकता है कि इसके स्रोत हो संकार्य CL
एक गतिशील पारी गिनती के लिए। इसलिए, एक अलग कॉलिंग कन्वेंशन की आवश्यकता होगी कि हम MOV
जो भी रजिस्टर इसमें पास किए गए थे ECX
, उससे इनपुट वैल्यू को एड करते हैं , जिसकी कीमत हमें 2 बाइट से चुकानी पड़ेगी। BT
अनुदेश का उपयोग कर सकते हैं किसी भी केवल 1 बाइट की लागत से, एक स्रोत के रूप में संकार्य रजिस्टर। तो, उस स्थिति में, यह बेहतर होगा।BT
कैरी फ़्लैग (CF) में संबंधित बिट का मान डालता है, इसलिए आप SETC
पूर्णांक रजिस्टर में उस मूल्य को प्राप्त करने के लिए एक निर्देश का उपयोग करेंगे, जैसे AL
कि यह कॉलर को वापस किया जा सकता है।
वैकल्पिक कार्यान्वयन, 23 बाइट्स
यहां एक वैकल्पिक कार्यान्वयन है जो यह निर्धारित करने के लिए मोडुलो और गुणन कार्यों का उपयोग करता है कि इनपुट मूल्य चिकन मैकगैग संख्या है या नहीं।
यह सिस्टम V AMD64 कॉलिंग कन्वेंशन का उपयोग करता है , जो EDI
रजिस्टर में इनपुट मूल्य को पास करता है । परिणाम अभी भी एक बूलियन है, में लौटा EAX
।
ध्यान दें, हालांकि, उपरोक्त कोड के विपरीत, यह एक उलटा बूलियन है (कार्यान्वयन सुविधा के लिए)। false
यदि इनपुट मान चिकन McNugget नंबर है, या true
इनपुट मान चिकन McNugget नंबर नहीं है , तो यह वापस आ जाता है ।
; bool IsNotMcNuggetNumber(int n)
; n is passed in EDI
8D 04 3F lea eax, [rdi+rdi*1] ; multiply input by 2, and put result in EAX
83 FF 2B cmp edi, 43
7D 0E jge TheEnd ; everything >= 43 is a McNugget number
99 cdq ; zero EDX in only 1 byte
6A 03 push 3
59 pop rcx ; short way to put 3 in ECX for DIV
F7 F1 div ecx ; divide input value by 3
6B D2 14 imul edx, edx, 20 ; multiply remainder of division by 20
39 D7 cmp edi, edx
0F 9C C0 setl al ; AL = (original input) < (input % 3 * 20)
TheEnd:
C3 ret
इसके बारे में जो कुरूप है वह शीर्ष पर तुलना-और-शाखा द्वारा इनपुट मान> = 43 को स्पष्ट रूप से संभालने की आवश्यकता है। जाहिर तौर पर ऐसा करने के अन्य तरीके भी हैं, जिन्हें करने की आवश्यकता नहीं है, जैसे कि केर्ड कॉइनरहाइडिंग का एल्गोरिथ्म , लेकिन यह एक बहुत अधिक बाइट्स को सांकेतिक शब्दों में बदलना होगा, इसलिए यह एक उचित समाधान नहीं है। मुझे लगता है कि मैं शायद कुछ बिट-टिडलिंग ट्रिक को याद कर रहा हूं, जो इस काम को अधिक भव्यता से कर देगा और ऊपर के बिटफील्ड-आधारित समाधान की तुलना में कम बाइट्स होगा (क्योंकि बिटफील्ड खुद को बहुत सारे बाइट्स को एन्कोडिंग करता है), लेकिन मैंने इसके लिए अध्ययन किया है थोड़ी देर और अभी भी इसे देख नहीं सकते।
ओह ठीक है, वैसे भी ऑनलाइन कोशिश करो !