C (gcc) , 26x20 = 520 25x19 = 475 23x17 = 391
#ifndef M //
#define M(a,b)a##b //
#define W(z,x)M(z,x) //
char*s,*S[]={"!!!!c",//
"8M !7! M8 878","77",//
"7!!MO887","788OM!!7"//
,"N7!78","7N87!"},r[5//
],*p=r;i=7;main(){for//
(;i--;)strstr(S[i],r)//
&&putchar("ITOJLSZ"[i//
]);} //
#endif //
__attribute__(( //
constructor(__LINE__)//
))W(f,__LINE__)(){s= //
" \
";*p++=strlen(s)+12;}//
मुझे हाल ही में जीएनयू के फ़ंक्शन विशेषताओं के बारे में बताया गया था, और सबसे दिलचस्प constructor
विशेषता यह थी, जो इस समस्या के लिए मेरे पहले के दृष्टिकोण में एक और अधिक गोलमटोल तरीके से जो मैं कर रहा था, उसके अधिक जटिल कार्यान्वयन के लिए अनुमति देता है।
विचार का जोर पहले की तरह ही है: एक स्ट्रिंग बनाएं और इसे सूची में खोजें ताकि यह पता लगाया जा सके कि किस कोड को ब्लॉक किया गया है। यह फ़ंक्शन को कॉल करके किया जाता है, प्रत्येक एक स्ट्रिंग में एक चरित्र जोड़ रहा है। जटिलता थी और बनी हुई है कि कार्यों की संख्या बदलती रहती है।
किसी फ़ंक्शन को परिभाषित करना attribute((constructor(x)))
इसे बनाता है ताकि फ़ंक्शन को पहले main()
दर्ज किया x
जा सके , वैकल्पिक होने के साथ प्राथमिकता (कम इसका मतलब यह पहले चलाया जाता है)। यह फ़ंक्शन पॉइंटर्स की आवश्यकता को हटा देता है, जो हमें एक मैक्रो, कुछ घोषणाओं और कॉलिंग चेन को छोड़ने की अनुमति देता है।
__LINE__
प्राथमिकता के लिए उपयोग करना iffy है, क्योंकि प्राथमिकता के स्तर 0-100 आरक्षित हैं। हालाँकि, यह त्रुटियों में परिणाम नहीं करता है, केवल चेतावनियाँ, और गोल्फ खेलते समय वे बहुत खुश होते हैं, इसलिए कुछ और क्या है?
यह प्राथमिकताओं का उपयोग नहीं करने के लिए एक और कॉलम बंद करने में मदद करेगा, लेकिन निष्पादन के क्रम को परिभाषित नहीं किया गया है। (वे इस मामले में उलट हैं, लेकिन अन्य परीक्षण अनिर्णायक हैं।)
यहाँ एल v2 का उदाहरण
पुराना, अधिक पोर्टेबल, दृष्टिकोण
#ifndef M //
#define M(a,b) a##b //
#define W(z,x)M(z,x) //
#define F W(f,__LINE__)//
#define A W(a,__LINE__)//
char r[5],*S[]={"####k"//
,";<<US##;",";##SU<<;",//
";;",";T<;#","<S #;# S"//
"< <;<","T;#;<"},*s,*p=//
r;i;typedef(*T)();T a17//
,a36,a55,a74;main(){for//
(a17(),a36&&a36(),a55&&//
a55(),a74&&a74();i--;) //
strstr(S[i],r)&&putchar//
("ILJOZTS"[i]);}i=7; //
#endif //
F();T A=F;F(){s= //
" \
";*p++=strlen(s)+12;} //
मेरी पसंदीदा समस्याओं में से एक मैंने इस साइट पर हल की है।
मुझे लगा कि प्रत्येक ब्लॉक किसी न किसी तरह से अपने स्वयं के निर्देशकों को विभाजित करेगा। पंक्तियों के साथ आसान है __LINE__
, और एक क्षैतिज शाब्दिक की लंबाई का उपयोग करके क्षैतिज रूप से आसन्न ब्लॉकों की संख्या पाई जा सकती है, जैसे:
char*s=//char*s=//
" "" "
; ;
परिणामी स्ट्रिंग की लंबाई लें और एक उचित संख्या से विभाजित करें और आपके पास चौड़ाई है। अफसोस की बात है, इस विधि से ब्लॉक से पहले कोई भी खाली जगह अदृश्य है। मुझे अभी भी संदेह है कि स्ट्रिंग्स का समाधान होगा, क्योंकि व्हॉट्सएप का अर्थ स्ट्रिंग्स के बाहर बहुत ही कम है, a+++b
बनाम जैसी चीजों में a+ ++b
। मैंने संक्षेप में ऐसा कुछ माना, लेकिन कुछ उपयोगी नहीं आ सका। एक और संभावना यह है कि पहचानकर्ताओं को एक साथ "चिपके" होने दिया जाए जहां ब्लॉक मिले:
A BA B
मुझे आश्चर्य नहीं होगा अगर यह अभी भी एक दिलचस्प समाधान के लिए बना सकता है।
अपनी सादगी के बावजूद, मुझे स्ट्रिंग समाधान खोजने में काफी समय लगा, जो इस खंड खंड पर आधारित है:
s=//
" \
";//
यदि फ़्रेग्मेंट का कोई क्षैतिज पड़ोसी नहीं है, तो दूसरी पंक्ति की न्यूलाइन बैकस्लैश द्वारा बच जाती है, जिससे लंबाई की एक स्ट्रिंग बन जाती है। 2. यदि, हालांकि, इसमें पड़ोसी है, तो बैकस्लैश इसके बजाय लाइन के शुरू होने पर क्वेश्चन मार्क से बच जाएगा। अगले ब्लॉक के 2:
s=//s=//
" \" \
";//";//
यह 5 की स्ट्रिंग "\" का निर्माण करेगा।
अधिक महत्वपूर्ण बात, यह ब्लॉक से पहले खाली जगह का पता लगाने के लिए भी अनुमति देता है:
s=//
" \
";//
फिर से, नईलाइन बच जाती है, और बाईं ओर खाली ब्लॉक का व्हाट्सएप लंबाई 6 के परिणामी स्ट्रिंग "" में शामिल है।
कुल मिलाकर एक पंक्ति पर ब्लॉक के सात अलग-अलग विन्यास हैं जिनके बारे में हमें चिंता करने की ज़रूरत है, और वे सभी अद्वितीय लंबाई के तार बनाते हैं:
2 " "
---
s=//
" \
";//
5 " \" "
---
s=//s=//
" \" \
";//";//
6 " "
---
s=//
" \
";//
9 " \" "
----
s=//s=//
" \" \
";//";//
10 " "
---
s=//
" \
";//
8 " \" \" "
---
s=//s=//s=//
" \" \" \
";//";//";//
11 " \" \" \" "
----
s=//s=//s=//s=//
" \" \" \" \
";//";//";//";//
अंतिम ब्लॉकों में निश्चित रूप से इतनी कम लंबाई नहीं होगी, लेकिन सिद्धांत ब्लॉक आकार की परवाह किए बिना समान है। यह भी बोनस है कि चौड़ाई का पता लगाने के लिए एक अलग तंत्र अनावश्यक है। परिणाम स्ट्रिंग के लिए इस स्ट्रिंग की लंबाई के अनुरूप एक चरित्र जोड़कर, 19 कॉन्फ़िगरेशन में से प्रत्येक एक अद्वितीय स्ट्रिंग प्राप्त करता है, जिसे सभी ब्लॉक चलाने के बाद केवल एक उपयुक्त सूची की तुलना में आवश्यकता होती है।
एक बार यह हल हो जाने के बाद, अगली बड़ी समस्या यह थी कि ब्लॉकों की प्रत्येक पंक्ति को "कैसे" देखा जाए। सी में, हम बहुत सीमित हैं जो कार्यों के बाहर किया जा सकता है। हमें भी main()
दिखाई देने की आवश्यकता है, लेकिन केवल एक बार। उत्तरार्द्ध आसानी से कुछ #define
एस द्वारा प्राप्त किया जाता है , लेकिन अगर हम चाहते हैं कि बाद के ब्लॉक का कोड अंदर हो main()
, तो यह समस्या कैसे पता करें कि अंतिम समापन घुंघराले ब्रैकेट को कब रखा जाए। आखिरकार, हम नहीं जानते कि वास्तव में ब्लॉक की कितनी पंक्तियों का उपयोग किया जाएगा। इसलिए हमें main()
स्थिर और किसी तरह बाकी को गतिशील होने की आवश्यकता है।
यदि अन्य ब्लॉक-पंक्तियों को स्व-समाहित किया जाना है, तो उन्हें कार्य करने की आवश्यकता है, लेकिन हमें यह सुनिश्चित करने की आवश्यकता है कि प्रत्येक फ़ंक्शन का एक नाम है जो अद्वितीय है, जबकि कॉल करने योग्य होने के लिए पर्याप्त रूप से अनुमानित भी है main()
। हमें यह जानने के लिए भी एक तंत्र की आवश्यकता है कि कौन से कार्य वास्तव में कहलाने के लिए हैं। अद्वितीय नाम बनाना हेल्पर मैक्रोज़ द्वारा हल किया जाता है:
#define M(a,b) a##b //
#define W(z,x)M(z,x) //
#define F W(f,__LINE__) //
#define A W(a,__LINE__) //
कॉलिंग F
एक पहचानकर्ता बनाएगी जिसका नाम f से शुरू होता है और लाइन नंबर के साथ समाप्त होता है। A
ऐसा ही करता है, लेकिन एक उपसर्ग के साथ, जिसका उपयोग समाधान के दूसरे भाग के लिए किया जाता है, जो फ़ंक्शन पॉइंटर्स है। हम चार ऐसे संकेत देते हैं:
typedef(*T)();T a17,a36,a55,a74;
चूंकि इन्हें वैश्विक चर के रूप में घोषित किया गया है, इसलिए इन्हें आसानी से NULL में सेट कर दिया गया है। बाद में, प्रत्येक ब्लॉक-पंक्ति में निम्नलिखित कोड कोड होगा:
F();T A=F;F()
यह पहले एक फ़ंक्शन की घोषणा करेगा, उस फ़ंक्शन को इंगित करने के लिए उपयुक्त फ़ंक्शन पॉइंटर को परिभाषित करेगा (हम केवल ग्लोबल्स को एक बार परिभाषित कर सकते हैं, लेकिन पहले की घोषणा को परिभाषा के रूप में नहीं गिना गया था, भले ही यह NULL के लिए प्रारंभ हुआ हो), और फिर वास्तविक को परिभाषित करें। समारोह। यह main()
किसी भी फ़ंक्शन पॉइंटर को कॉल करने की अनुमति देता है जो गैर-NULL (a17 कभी भी NULL नहीं होगा):
a17(),a36&&a36(),a55&&a55(),a74&&a74()
ऐसा करने से स्ट्रिंग का निर्माण होगा r
, जिसे तब स्ट्रिंग की तालिका में देखा जाता है और यदि पाया जाता है, तो उपयुक्त अक्षर आउटपुट है।
केवल शेष चाल यह है कि जब भी अस्पष्टता से बचा जा सकता है, या अतिव्यापी तार को भ्रमित किया जा सकता है, तब मैच के लिए तार की सूची को छोटा कर दिया गया था।
यहाँ एल v2 का उदाहरण