C, 59 ไบต์
i;f(char*s){while(*s&3?*s&9||(i+=i+*s%5):putchar(i),*s++);}
ตัวเลขเวทย์มนตร์หมายเลขเวทย์มนตร์ทุกที่!
(นอกจากนี้ C สั้นกว่า Python, JS, PHP และ Ruby ไม่เคยได้ยินจาก!)
นี่คือฟังก์ชันที่รับสตริงเป็นอินพุตและเอาต์พุตไปยัง STDOUT
เกมส์
โครงสร้างพื้นฐานคือ:
i; // initialize an integer i to 0
f(char*s){
while(...); // run the stuff inside until it becomes 0
}
ที่นี่ "สิ่งที่อยู่ภายใน" คือพวงของรหัสตามด้วยโดย,*s++
ที่เครื่องหมายจุลภาคส่งกลับค่าของอาร์กิวเมนต์ที่สองเท่านั้น ดังนั้นสิ่งนี้จะทำงานผ่านสตริงและตั้งค่า*s
เป็นตัวละครทุกตัวรวมถึงการต่อท้าย NUL ไบต์ (เนื่องจาก postfix ++
คืนค่าก่อนหน้า) ก่อนที่จะออก
ลองดูที่เหลือ:
*s&3?*s&9||(i+=i+*s%5):putchar(i)
การลอกแบบไตรภาคและการลัดวงจรออกไปสิ่ง||
นี้สามารถขยายได้
if (*s & 3) {
if (!(*s & 9)) {
i += i + *s % 5;
}
} else {
putchar(i);
}
หมายเลขมายากลเหล่านี้มาจากไหน นี่เป็นตัวแทนไบนารีของตัวละครทั้งหมดที่เกี่ยวข้อง:
F 70 01000110
B 66 01000010
i 105 01101001
z 122 01111010
u 117 01110101
32 00100000
\0 0 00000000
ก่อนอื่นเราต้องแยกช่องว่างและ NUL ออกจากตัวละครที่เหลือ วิธีการทำงานของอัลกอริธึมนี้จะเก็บสะสมของหมายเลข "ปัจจุบัน" และพิมพ์เมื่อใดก็ตามที่มันมาถึงช่องว่างหรือจุดสิ้นสุดของสตริง (เช่น'\0'
) โดยการสังเกตว่า' '
และ'\0'
เป็นตัวอักษรเพียงตัวเดียวที่ไม่มีชุดบิตที่มีนัยสำคัญน้อยที่สุดสองชุดเราสามารถ bitwise และอักขระที่มี0b11
ศูนย์เป็นศูนย์ได้ถ้าอักขระนั้นมีช่องว่างหรือ NUL และไม่ใช่ศูนย์
ขุดลึกลงไปในครั้งแรก "ถ้า" FBizu
สาขาตอนนี้เรามีตัวละครที่เป็นหนึ่งใน ฉันเลือกที่จะอัปเดตแอคคอมมูเลเตอร์F
ของ s และB
s เท่านั้นดังนั้นฉันต้องการวิธีการกรองizu
s สะดวกF
และB
ทั้งสองชุดมีบิตที่สำคัญน้อยที่สองสามหรือเจ็ดและตัวเลขอื่น ๆ ทั้งหมดมีบิตอื่น ๆ อย่างน้อยหนึ่งชุด ในความเป็นจริงพวกเขาทั้งหมดมีบิตที่มีนัยสำคัญน้อยที่สุดที่หนึ่งหรือสี่ ดังนั้นเราสามารถบิตและด้วย0b00001001
ซึ่งก็คือ 9 ซึ่งจะให้ 0 F
และB
และไม่ใช่ศูนย์อื่น ๆ
เมื่อเราได้พิจารณาแล้วว่าเรามีF
หรือB
เราสามารถ map ให้พวกเขา0
และ1
ตามลำดับโดยการโมดูลัสของพวกเขา 5 เพราะF
เป็น70
และเป็นB
66
จากนั้นตัวอย่าง
i += i + *s % 5;
เป็นเพียงวิธีการตีกอล์ฟ
i = (i * 2) + (*s % 5);
ซึ่งสามารถแสดงเป็น
i = (i << 1) | (*s % 5);
ซึ่งแทรกบิตใหม่ที่ตำแหน่งสำคัญน้อยที่สุดและเลื่อนทุกอย่างอื่นไป 1
"แต่เดี๋ยวก่อน!" คุณอาจประท้วง "หลังจากที่คุณพิมพ์i
จะได้รับการรีเซ็ตเป็น 0 เมื่อใด" ทีนี้putchar
มันปลดการทะเลาะกันของมันunsigned char
ซึ่งมันก็มีขนาด 8 บิต นั่นหมายความว่าทุกอย่างที่ผ่านบิตที่สำคัญน้อยที่สุดที่ 8 (เช่นขยะจากการทำซ้ำก่อนหน้านี้) ถูกโยนทิ้งไปและเราไม่จำเป็นต้องกังวลเกี่ยวกับมัน
ขอบคุณ@ETHproductions ที่แนะนำให้แทนที่57
ด้วย9
การบันทึกไบต์!