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 মেশিন কোডে একটি ফাংশন সংজ্ঞায়িত করে যা ইনপুট মানটি চিকেন ম্যাকনুগেট নম্বর কিনা তা নির্ধারণ করে। উইন্ডোজটিতে ব্যবহৃত মাইক্রোসফ্ট 64৪-বিট কলিং কনভেনশনECX
অনুসরণ করে একটি একক পজিটিভ পূর্ণসংখ্যা প্যারামিটারটি রেজিস্টারে পাস করা হয় । ফলাফলটি বুলিয়ান মানটিতে ফিরে আসেEAX
রেজিস্টারে ।
অবহেলিত সমাবেশ মেমোনমিক্স:
; 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
স্পষ্টতই, এটি প্রচন্ডভাবে বন্ধ রয়েছে পাইথনের অ্যান্ডারস কাসেরগের সমাধান থেকে , এটি চিকেন ম্যাকনুগেট সংখ্যার মানকে উপস্থাপন করার জন্য একটি বিট-ফিল্ডের চারপাশে তৈরি। বিশেষত, এই ক্ষেত্রের প্রতিটি বিট যা একটি বৈধ চিকেন ম্যাকনুগেট সংখ্যার সাথে মিলে যায়; অন্যান্য সমস্ত বিট 0 তে সেট করা আছে (এটি 0 টি একটি বৈধ চিকেন ম্যাকনুগেট নম্বর হিসাবে বিবেচনা করে তবে আপনি যদি এটি পছন্দ না করেন তবে আপনার পছন্দটি একক-বিট পরিবর্তন হবে))
আমরা খালি একটি রেজিস্টার এ মান লোড করে শুরু। এটি একটি -৪-বিটের মান, যা ইতিমধ্যে এনকোড করতে by বাইট লাগে, এবং আমাদের একটি বাইট রেক্স.ডাব্লু উপসর্গ প্রয়োজন, তাই আমরা বাইটের ক্ষেত্রে সত্যই বেশ ব্যয় করছি, তবে এটি সমাধানের হৃদয়, তাই আমার ধারণা এটি মূল্যবান worth
তারপরে আমরা ইনপুট মান দ্বারা ক্ষেত্রটি ডানদিকে সরান। * অবশেষে, আমরা সর্বনিম্ন-অর্ডার বিট ব্যতীত অন্য সবকেই মুখোশ করি এবং এটি আমাদের বুলিয়ান ফলাফল হয়ে যায়।
তবে, যেহেতু আপনি বাস্তবে বিটের সংখ্যার চেয়ে বেশি পরিমাণে স্থানান্তর করতে পারবেন না, এটি কেবল 0-63 থেকে ইনপুটগুলির জন্য কাজ করে। উচ্চতর ইনপুট মানগুলিকে সমর্থন করার জন্য, আমরা ফাংশনের শীর্ষে একটি পরীক্ষা সন্নিবেশ করি যা ইনপুট মানটির নীচে শাখা হয়> = 64 this এটি সম্পর্কে আকর্ষণীয় কেবলমাত্র আমরা বিট-ফিল্ডের ধ্রুবকে প্রিললোড করি RAX
এবং তারপরে শাখা করি branch নীচে যে নির্দেশটি সর্বনিম্ন-অর্ডার বিটটি বন্ধ করে দেয়, এটি নিশ্চিত করে যে আমরা সর্বদা 1 এ ফিরে আসছি।
এটি অনলাইন চেষ্টা করুন!
(সেখানকার সি ফাংশন কলটি এমন একটি বৈশিষ্ট্যের সাথে টীকাযুক্ত করা হয়েছে যার ফলে আমার এসেম্বলি কোডটি মাইক্রোসফ্ট কলিং কনভেনশন ব্যবহার করে জিসিসি কল করেছে। টিআইও যদি এমএসভিসি সরবরাহ করে তবে এটি প্রয়োজনীয় হবে না))
__
* শিফটের বিকল্প হিসাবে, আমরা x86 BT
নির্দেশ ব্যবহার করতে পারতাম , তবে এনকোড করতে এটি 1 বাইট বেশি দীর্ঘ, সুতরাং কোনও সুবিধা নেই। আমরা না হলে বাধ্য হয়ে আলাদা কলিং কনভেনশন ব্যবহার করা হয় যা ECX
নিবন্ধে ইনপুট মানটি স্বাচ্ছন্দ্যে পাস করে না। এই সমস্যা হবে কারণ SHR
প্রয়োজন যে তার উত্স হতে প্রতীক CL
একটি গতিশীল শিফট গণনা জন্য। অতএব, একটি ভিন্ন কলিং কনভেনশনের জন্য আমাদের যে MOV
কোনও নিবন্ধ ECX
যা পাস করে তা থেকে ইনপুট মানটি সম্পাদন করা দরকার , যার জন্য আমাদের 2 বাইট খরচ পড়বে। BT
নির্দেশ ব্যবহার করতে পারেন কোন মাত্র 1 বাইট একটি খরচে, একটি উৎস প্রতীক হিসাবে নিবন্ধিত। সুতরাং, এই পরিস্থিতিতে, এটি আরও ভাল হবে।BT
আনুষঙ্গিক বিটের মান ক্যারি ফ্ল্যাগে (সিএফ) রাখে, যাতে আপনি সেই ব্যবহার করেনSETC
কোনও পূর্ণসংখ্যার রেজিষ্টারে এই মানটি পাওয়ার নির্দেশনা AL
যাতে এটি কলারের কাছে ফিরিয়ে দেওয়া যায়।
বিকল্প বাস্তবায়ন, 23 বাইট
ইনপুট মানটি চিকেন ম্যাকনুগেট নম্বর কিনা তা নির্ধারণ করতে এখানে একটি বিকল্প প্রয়োগ রয়েছে যা মডুলো এবং গুণক ক্রিয়াকলাপগুলি ব্যবহার করে।
এটি সিস্টেম ভি এমডি 64 কলিং কনভেনশন ব্যবহার করে , যা EDI
রেজিস্টারে ইনপুট মানটি পাস করে । ফলাফলটি এখনও একটি বুলিয়ান, ফিরে এসেছিল EAX
।
দ্রষ্টব্য, যদিও, উপরের কোডটির বিপরীতে, এটি একটি বিপরীত বুলিয়ান (বাস্তবায়নের সুবিধার জন্য)। false
ইনপুট মানটি যদি চিকেন ম্যাকনুগেট নম্বর হয় বা true
ইনপুট মানটি যদি চিকেন ম্যাকনুগেট নম্বর না হয় তবে এটি ফিরে আসে ।
; 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 পরিচালনা করতে হবে। এটি করার স্পষ্টরূপে অন্যান্য উপায় রয়েছে যেগুলি যেমন শাখার প্রয়োজন হয় না স্পষ্টরূপে কায়ার্ড কইনারিংহিংয়ের অ্যালগরিদমের মতো , তবে এটি অনেক সময় নেয় এনকোড করতে আরও বাইট লাগবে, সুতরাং এটি কোনও যুক্তিসঙ্গত সমাধান নয়। আমি অনুভব করেছি যে আমি সম্ভবত কিছু বিট-টুইডলিং ট্রিক মিস করছি যা এই কাজটি আরও মার্জিতভাবে তৈরি করবে এবং উপরের বিটফিল্ড-ভিত্তিক সমাধানের চেয়ে কম বাইট হবে (যেহেতু বিটফিল্ডটি এনকোডিং করার ফলে অনেকগুলি বাইট লাগে) তবে আমি এটির জন্য গবেষণা করেছি কিছুক্ষণ পরেও তা দেখতে পাচ্ছে না।
ওহ ভাল, যাইহোক এটি অনলাইন চেষ্টা করুন !