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 ที่กำหนดว่าค่าอินพุตเป็นหมายเลข Chicken McNugget หรือไม่ พารามิเตอร์จำนวนเต็มบวกเดียวจะถูกส่งผ่านในการECX
ลงทะเบียนตามการเรียกใช้Microsoft 64 บิตที่ใช้บน Windows ผลลัพธ์คือค่าบูลีนที่ส่งคืนในEAX
รีจิสเตอร์
คำย่อของชุดประกอบ Ungolfed:
; 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
เห็นได้ชัดว่าสิ่งนี้เล่นกันอย่างหนักในโซลูชันของAnders Kaseorg ใน Pythonซึ่งมีพื้นฐานมาจากบิตฟิลด์ซึ่งแสดงถึงค่าที่เป็นตัวเลข Chicken McNugget โดยเฉพาะแต่ละบิตในฟิลด์นี้ที่สอดคล้องกับหมายเลข Chicken McNugget ที่ถูกต้องถูกตั้งค่าเป็น 1 บิตอื่น ๆ ทั้งหมดถูกตั้งค่าเป็น 0 (ซึ่งถือว่า 0 เป็นหมายเลข Chicken McNugget ที่ถูกต้อง แต่ถ้าคุณไม่ชอบสิ่งนั้นการตั้งค่าของคุณจะเป็นการแก้ไขแบบบิตเดียว)
เราเริ่มต้นโดยเพียงแค่โหลดค่านี้ในการลงทะเบียน มันเป็นค่า 64- บิตซึ่งใช้เวลา 8 ไบต์ในการเข้ารหัสและเราจำเป็นต้องใช้คำนำหน้า REX หนึ่งไบต์ดังนั้นเราจึงใช้เวลาค่อนข้างน้อยในแง่ของไบต์ แต่นี่คือหัวใจของการแก้ปัญหาดังนั้น ฉันคิดว่ามันคุ้มค่า
จากนั้นเราเลื่อนฟิลด์ไปทางขวาด้วยค่าอินพุต * * * *สุดท้ายเราปิดบังทั้งหมดยกเว้นบิตลำดับต่ำสุดและนั่นกลายเป็นผลบูลีนของเรา
อย่างไรก็ตามเนื่องจากคุณไม่สามารถเลื่อนได้มากกว่าจำนวนบิตในค่านี้จะใช้งานได้กับอินพุตตั้งแต่ 0-63 เท่านั้น เพื่อรองรับค่าอินพุตที่สูงขึ้นเราใส่การทดสอบที่ด้านบนของฟังก์ชั่นที่สาขาไปยังด้านล่างของค่าอินพุตคือ> = 64 สิ่งเดียวที่น่าสนใจเกี่ยวกับเรื่องนี้คือเราโหลดค่าคงที่บิตฟิลด์ล่วงหน้าRAX
แล้วสาขา ลงไปที่คำสั่งที่ปิดบังบิตลำดับต่ำสุดดังนั้นจึงมั่นใจได้ว่าเราจะส่งคืน 1 เสมอ
ลองออนไลน์!
(การเรียกฟังก์ชัน C นั้นมีหมายเหตุประกอบกับแอตทริบิวต์ที่ทำให้ GCC เรียกใช้โดยใช้หลักการเรียก Microsoft ที่รหัสแอสเซมบลีของฉันใช้ถ้า TIO ให้ MSVC สิ่งนี้ไม่จำเป็น)
__
* เป็นอีกทางเลือกหนึ่งในการเปลี่ยนเราสามารถใช้BT
คำสั่งx86 ได้แต่นั่นยาว 1 ไบต์ในการเข้ารหัสดังนั้นจึงไม่มีข้อได้เปรียบ นอกจากว่าเราถูกบังคับให้ใช้แบบแผนการโทรที่แตกต่างกันซึ่งไม่ผ่านค่าอินพุตในการECX
ลงทะเบียน นี่จะเป็นปัญหาเนื่องจากSHR
ต้องการให้ตัวถูกดำเนินการต้นทางของมันCL
สำหรับการนับกะแบบไดนามิก ดังนั้นแบบแผนการโทรที่แตกต่างกันนั้นต้องการให้เราMOV
แก้ไขค่าอินพุตจากสิ่งที่รีจิสเตอร์มันถูกส่งไปยังECX
ซึ่งจะทำให้เรามีค่า 2 ไบต์ BT
การเรียนการสอนสามารถใช้ใด ๆ ที่ลงทะเบียนเป็นผู้ถูกดำเนินการแหล่งที่มาที่ค่าใช้จ่ายเพียง 1 ไบต์ ดังนั้นในสถานการณ์นั้นมันจะดีกว่าBT
ทำให้ค่าของบิตที่สอดคล้องกันเข้าไปธงพก (CF) ดังนั้นคุณจะใช้SETC
คำสั่งเพื่อรับค่านั้นในรีจิสเตอร์จำนวนเต็มเช่นAL
นั้นมันจะถูกส่งกลับไปยังผู้เรียก
การติดตั้งทางเลือก 23 ไบต์
นี่คือการดำเนินการทางเลือกที่ใช้โมดูโลและการดำเนินการคูณเพื่อตรวจสอบว่าค่าอินพุตเป็นหมายเลข Chicken McNugget
มันใช้หลักการเรียกประชุม System V AMD64ซึ่งส่งผ่านค่าอินพุตในEDI
รีจิสเตอร์ EAX
ผลที่ได้ก็ยังคงเป็นแบบบูลกลับมาใน
อย่างไรก็ตามโปรดทราบว่าสิ่งนี้ต่างจากรหัสด้านบนนี่คือบูลีนผกผัน (เพื่อความสะดวกในการติดตั้ง) มันจะส่งคืนfalse
ถ้าค่าอินพุตเป็นหมายเลข Chicken McNugget หรือtrue
ถ้าค่าอินพุตไม่ใช่หมายเลข Chicken 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 โดยเปรียบเทียบและสาขาที่ด้านบน เห็นได้ชัดว่ามีวิธีการอื่นในการทำเช่นนี้ซึ่งไม่ต้องการการแยกย่อยเช่นอัลกอริทึมของ caird coinheringaahingแต่การเข้ารหัสนี้ต้องใช้จำนวนไบต์ที่มากขึ้นดังนั้นจึงไม่ใช่ทางออกที่สมเหตุสมผล ฉันคิดว่าฉันอาจพลาดเคล็ดลับที่ทำให้การทำงานนี้ออกมาสวยงามและมีจำนวนไบต์น้อยกว่าโซลูชันที่ใช้บิตฟิลด์ข้างต้น (เนื่องจากการเข้ารหัสบิตฟิลด์เองนั้นใช้ไบต์จำนวนมาก) แต่ฉันได้ศึกษาเรื่องนี้ ครู่หนึ่งและยังไม่เห็น
ลองดูออนไลน์กันดีกว่า!