सी, 59 बाइट्स
i;f(char*s){while(*s&3?*s&9||(i+=i+*s%5):putchar(i),*s++);}
मैजिक नंबर, मैजिक नंबर हर जगह!
(इसके अलावा, पायथन, जेएस, पीएचपी और रूबी से कम सी? अनसुना!)
यह एक फ़ंक्शन है जो इनपुट के रूप में एक स्ट्रिंग लेता है और STDOUT को आउटपुट करता है।
पूर्वाभ्यास
मूल संरचना है:
i; // initialize an integer i to 0
f(char*s){
while(...); // run the stuff inside until it becomes 0
}
यहां, "सामान के अंदर" कोड का एक गुच्छा है ,*s++
, जिसके बाद अल्पविराम ऑपरेटर अपने दूसरे तर्क का केवल मूल्य देता है। इसलिए, यह स्ट्रिंग के माध्यम से चलेगा और बाहर निकलने से पहले, *s
NUL बाइट (पोस्टफ़िक्स ++
पिछले मूल्य को वापस करने के बाद ) सहित प्रत्येक वर्ण पर सेट होगा ।
आइए बाकी पर एक नज़र डालें:
*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'
केवल दो ही महत्वपूर्ण बिट्स सेट नहीं करने के लिए एकमात्र वर्ण हैं, हम 0b11
चरित्र को स्थान या NUL और नॉनज़ेरो अन्यथा शून्य कर सकते हैं।
गहरी खुदाई, पहले "अगर" शाखा में, अब हमारे पास एक ऐसा चरित्र है जो एक है FBizu
। मैंने केवल F
एस और B
एस पर संचायक को अपडेट करने के लिए चुना , इसलिए मुझे एस को फ़िल्टर करने के लिए किसी तरह की आवश्यकता थी izu
। आसानी से, F
और B
दोनों के पास केवल दूसरा, तीसरा या सातवाँ महत्वपूर्ण बिट सेट है, और अन्य सभी नंबरों में कम से कम एक बिट सेट है। वास्तव में, वे सभी पहले या चौथे कम से कम महत्वपूर्ण बिट हैं। इसलिए, हम बिटवाइज़ कर सकते हैं और साथ 0b00001001
, है, जो 9 के लिए 0 निकलेगा जो F
और B
और अशून्य अन्यथा।
एक बार हमने तय किया है कि हम एक है कि F
या B
तो हम उनका मैप कर सकते हैं 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
इसके तर्क को a में रखता है unsigned char
, जो कि आकार में 8 बिट्स होता है। इसका मतलब है कि 8 वीं सबसे कम महत्वपूर्ण बिट (यानी पिछले पुनरावृत्तियों से रद्दी) को फेंक दिया गया है, और हमें इसके बारे में चिंता करने की आवश्यकता नहीं है।
के लिए धन्यवाद @ETHproductions को बदलने के लिए सुझाव देने के लिए 57
साथ 9
, एक बाइट बचत!