🧩 हैलो कहने के लिए उनतीस बाइट्स: SuperHack में “Hello, World!” की कोड गोल्फिंग 🔗

hacker.org के “Super Small Hello World” चैलेंज का एक विस्तृत विवरण: वे समाधान जिन्होंने काम किया, वे जो लगभग सफल रहे, और वह ट्रिक जिसने अंततः 29 का आँकड़ा छुआ।

Overview

📑 विषय-सूची 🔗


🎯 चुनौती (The challenge) 🔗

hacker.org पर SuperHack नाम की एक छोटी सी गूढ़ (esoteric) प्रोग्रामिंग भाषा है। कार्य सुनने में बहुत मामूली लगता है: एक ऐसा SuperHack प्रोग्राम लिखें जो Hello, World! प्रिंट करे।

असली पेच स्कोर में है। आपको आपके कोड के बाउंडिंग रेक्टेंगल (आयत) के क्षेत्रफल (area) के आधार पर स्कोर दिया जाता है, और यह जितना छोटा हो उतना बेहतर है। प्रोग्राम को सही तरीके से समाप्त भी होना चाहिए: ! (halt) निर्देश को निष्पादित करके। टेक्स्ट प्रिंट होने के बाद VM एक्सेप्शन के साथ क्रैश होने की गिनती नहीं होती, और न ही अनावश्यक बाइट्स प्रिंट करने की अनुमति है।

हराने के लिए लक्ष्य संख्या 29 थी।


🧭 SuperHack का दो मिनट का परिचय 🔗

SuperHack एक 2-D स्टैक मशीन है, जो भावना में Befunge के समान है:

निर्देश (Instruction)प्रभाव (Effect)
0-9एक अंक पुश (push) करें
+ - dजोड़ें, घटाएँ, फ़्लोर-डिवाइड करें (शून्य से d करने पर 0 मिलता है)
xस्टैक के शीर्ष (top) की प्रतिलिपि बनाएँ
n ^शीर्ष से n नीचे वाले आइटम की एक प्रति पुश करें (1^ दूसरे आइटम की प्रति बनाता है)
,इनपुट पढ़ें। जब कोई इनपुट नहीं होता है, तो यह 0 पुश करता है
gx पॉप करें, y पॉप करें, (x, y) पर स्थित कैरेक्टर कोड पुश करें। ग्रिड के बाहर यह 0 पुश करता है
Pपॉप करें और एक अक्षर के रूप में प्रिंट करें (केवल निचले 7 बिट्स)
sअगली सेल को छोड़ दें (skip)
?पॉप करें; यदि मान 0 था तो अगली सेल को छोड़ दें
@वर्तमान पोजीशन (और दिशा) को कॉल स्टैक पर पुश करें
$एक पोजीशन पॉप करें, वहाँ जंप करें, और दो सेल आगे से जारी रखें
\दर्पण (mirror): “दाईं ओर जाने” को “नीचे की ओर जाने” में बदल देता है
!प्रोग्राम रोकें (halt)
अन्य कुछ भीकोई ऑपरेशन नहीं (no-op)

दो परिणाम आगे आने वाली हर चीज़ को आकार देते हैं:

  1. अक्षर ही डेटा हैं। g प्रोग्राम के अपने कोड को पढ़ता है, इसलिए स्ट्रिंग Hello, World! सीधे ग्रिड में रह सकती है और एक समय में एक अक्षर करके वापस पढ़ी जा सकती है। निष्पादित होने पर इसके अधिकांश अक्षर (H e l o W r) no-op होते हैं। तीन नहीं हैं: , 0 पुश करता है, d विभाजित करता है, और ! प्रोग्राम को रोक देता है।
  2. @ / $ लूप बनाते हैं, और लूप की गिनती इस बात पर निर्भर करती है कि @ कहाँ हैं। $ जिस @ पर लौटता है, उसके दो सेल बाद से काम शुरू करता है। वह अगले @ पर उतरता है, जो खुद को फिर से पुश करता है, इसलिए कुछ @ लूप बॉडी को कई बार चला सकते हैं:
    • आसन्न (Adjacent) @@@@@ फिबोनाची (Fibonacci) गिनती देते हैं। उनमें से पाँच बॉडी को ठीक 13 बार चलाते हैं।
    • दो सेल की दूरी पर रखे गए @ दो की घात (powers of two) देते हैं। उनमें से चार 16 राउंड (passes) की अनुमति देते हैं।

तेरह अक्षर, तेरह राउंड। इसे ध्यान में रखें।

क्षेत्रफल चौड़ाई गुणा ऊँचाई है, और 29 एक अभाज्य संख्या (prime number) है। इसलिए 29-सेल का प्रोग्राम एक एकल पंक्ति (row) या एक एकल कॉलम (column) ही होना चाहिए।


1️⃣ समाधान 1: सीधा-सादा लूप (क्षेत्रफल 32) 🔗

Solution 1 annotated

Hello, World!%0@s!@@@@@ 01^gP1+$

पहला वास्तविक समाधान पेलोड (डेटा) को सामने रखता है और उसके बाद निष्पादन (execution) शुरू करता है:

हिस्साभूमिका
Hello, World!डेटा, कभी निष्पादित नहीं होता, क्योंकि PC % से शुरू होता है
%प्रवेश बिंदु (entry point)
0इंडेक्स i = 0
@ s !हॉल्ट गैजेट (halt gadget): नीचे देखें
@@@@@पाँच आसन्न ट्रैम्पोलिन, इसलिए बॉडी 13 बार चलती है
पैडिंग (नीचे समझाया गया है)
0 1^ gपंक्ति 0 पुश करें, i कॉपी करें, फिर कॉलम i से अक्षर प्राप्त करें
Pइसे प्रिंट करें
1+i += 1
$लूप

हॉल्ट गैजेट। पहला @ कॉल स्टैक के सबसे निचले हिस्से में अपनी पोजीशन रखता है, और s, ! के ऊपर से जंप कर जाता है। फिर फिबोनाची श्रृंखला अपने 13 राउंड पूरे करती है। जब कॉल स्टैक अंततः खुलते हुए उस पहले @ तक पहुँचता है, तो $ उसके दो सेल बाद फिर से शुरू होता है, जो कि ठीक ! है। प्रोग्राम साफ-सुथरे ढंग से रुक जाता है, और कहीं भी स्ट्रिंग के अंत की जाँच (end-of-string test) करने की ज़रूरत नहीं पड़ती।

पैडिंग। आसन्न @ के साथ, अंतिम @ से लौटने पर निष्पादन दो सेल बाद शुरू होता है, जो श्रृंखला के बाद पहली सेल को छोड़ देता है। इसलिए वह सेल कुछ हानिरहित होनी चाहिए, इसीलिए वहाँ एक स्पेस (खाली जगह) है।

परिणाम: Hello, World!, साफ-सुथरा हॉल्ट, क्षेत्रफल 32। यह सही है लेकिन बड़ा है: पेलोड निष्क्रिय भार की तरह है, और %, पैडिंग तथा 0 मिलकर तीन सेल खर्च करते हैं।


2️⃣ समाधान 2: इंटरलीविंग (क्षेत्रफल 28, लेकिन अमान्य) 🔗

Solution 2 annotated

1H@e@l@l@o ,1 ^WgoPr2lsds!+$

अगला विचार अलग पेलोड पर सेल खर्च करना बंद करना और स्ट्रिंग को कोड के बीच में बुनना (interleave करना) है। Hello, World! के अक्षर विषम (odd) कॉलम (1, 3, …, 25) में बैठते हैं, और कोड उनके बीच के सम (even) कॉलम को भरता है:

समस्या यह है कि 16 राउंड 13 से अधिक हैं। स्ट्रिंग को प्रिंट करने के बाद, लूप अंत के आगे भी अक्षर लाता रहता है और $ तथा दो NUL बाइट्स प्रिंट कर देता है। फिर $ कॉल स्टैक को खाली पाता है और VM क्रैश हो जाता है:

output:  "Hello, World!$\0\0"
message: call stack underflow

यह छोटा है, लेकिन यह कोई मान्य समाधान नहीं है। हालांकि, यह एक मुख्य विचार पेश करता है: पेलोड के वे अक्षर जो उपयोगी निर्देश भी हैं (,), डेटा और कोड दोनों के रूप में दोहरा काम करते हैं।


3️⃣ समाधान 3: लंबवत (Vertical) जाना (क्षेत्रफल 27, लेकिन अमान्य) 🔗

Solution 3 annotated

\
2
H
@
e
@
l
@
l
@
o
x
,
g

P
W
2
o
+
r
$
l

d

!

(प्रति पंक्ति एक अक्षर। खाली पंक्तियाँ सिंगल स्पेस हैं, जो डेटा हैं।)

प्रोग्राम को घुमाकर खड़ा (लंबवत) करने का एक अप्रत्याशित लाभ होता है। एक एकल कॉलम में, g को x-कोऑर्डिनेट के 0 होने और पंक्ति (row) के i होने की आवश्यकता होती है। पेलोड का , वह 0 मुफ्त में प्रदान करता है, इसलिए अक्षर लाने का काम सिकुड़कर x , g रह जाता है: i की प्रतिलिपि बनाएँ, 0 पुश करें, प्राप्त करें। इसकी कीमत PC को नीचे की ओर मोड़ने के लिए सबसे ऊपर लगाया गया एक \ है।

हालांकि, इसमें भी समाधान 2 वाली ही खामी है। लूप आगे निकल जाता है, NUL बाइट्स प्रिंट करता है, और call stack underflow में समाप्त होता है। क्षेत्रफल 27 पर यह इस पोस्ट का सबसे छोटा प्रोग्राम है, लेकिन यह मान्य नहीं है।

समाधान 2 और 3 से सबक यह मिलता है कि साफ-सुथरे ढंग से रुकने में सेल्स खर्च होती हैं। इंटरलीविंग लूप को सस्ता बनाती है, लेकिन यह आपको 16 राउंड देती है जबकि आपको ठीक 13 की आवश्यकता होती है।


4️⃣ समाधान 4: बाहर निकलने (Exit) की कीमत चुकाना (क्षेत्रफल 30) 🔗

Solution 4 annotated

\
2
H
@
e
@
l
@
l
@
o
x
,
g
 
P
W
x
o
5
r
d
l
5
d
?
!
2
+
$

समाधान 4, समाधान 3 के लंबवत इंटरलीव को बनाए रखता है और एक वास्तविक एंड-ऑफ-स्ट्रिंग टेस्ट जोड़ता है:

पंक्ति(याँ)सेल्सभूमिका
0\नीचे की ओर मुड़ें
12i = 2
3, 5, 7, 9@चार ट्रैम्पोलिन, अधिकतम 16 राउंड
11-13x , gपंक्ति i प्राप्त करें (, पेलोड है)
15Pप्रिंट करें
17-24x 5 d 5 dमान floor(floor(i/5)/5) = floor(i/25) की जाँच करें (अंतिम d पेलोड है)
25?यदि टेस्ट 0 है, तो अगली सेल को छोड़ दें…
26!…जो कि पेलोड का अपना ! है
27-282 +i += 2
29$लूप

इंडेक्स 2, 4, …, 26 तक चलता है। floor(i/25) बिल्कुल अंतिम अक्षर (i = 26) तक 0 रहता है, इसलिए ? अंतिम को छोड़कर हर राउंड में हॉल्ट को छोड़ देता है। अंतिम राउंड में, निष्पादन पेलोड के ! पर पड़ता है, जो एक साथ प्रिंट किया गया अंतिम अक्षर भी है और प्रोग्राम को रोकने वाला निर्देश भी।

यह पुन: उपयोग (reuse) का एक शानदार नमूना है: पेलोड के ,, d और ! सभी कोड के रूप में काम करते हैं। लेकिन टेस्ट में पाँच सेल खर्च होते हैं, और कुल योग 30 होता है।

🧱 29 असंभव क्यों लग रहा था 🔗

इस बिंदु पर मेरे AI साथी ने यह साबित करने की कोशिश की कि 30 ही सर्वोत्तम (optimal) है। हर तरीका एक ही दीवार से टकराता हुआ प्रतीत हो रहा था:

छोटे क्षेत्रफलों की गहन मशीन खोजों में कुछ नहीं मिला, और क्षेत्रफल 29 पर समाधान 4 के लेआउट के आसपास की खोजों में भी कुछ नहीं मिला। “30 ही न्यूनतम सीमा है” एक प्रमेय (theorem) की तरह दिखने लगा।

लेकिन ऐसा नहीं था।


🏆 समाधान 5: उनतीस (क्षेत्रफल 29) 🔗

Solution 5 annotated

9@s!@@@@@Hello, Worlä¡1^gP1+$

सफलता जज (judge) के सोर्स कोड को दोबारा पढ़ने से मिली। दो पंक्तियाँ मायने रखती हैं:

case 'P':
  $output .= chr($this->Pop() & 0x7F); break;
...
default:
  break;   // every unknown character is a no-op

इसलिए प्रत्येक पेलोड अक्षर की दो एनकोडिंग होती हैं। साधारण एनकोडिंग निष्पादित होने पर कुछ कर सकती है। जबकि c | 0x80 वाली एनकोडिंग के निष्क्रिय (inert) होने की गारंटी है। यही “डेटा का फ़ॉर्मूला” है: खतरनाक अक्षरों को c + 128 के रूप में स्टोर करें, और P को मुफ्त में हाई बिट हटाने दें।

केवल दो पेलोड अक्षर खतरनाक हैं: d बन जाता है ä (0xE4) और ! बन जाता है ¡ (0xA1)। उन दोनों के बदलने के साथ, पूरे पेलोड को निष्पादित किया जा सकता है। यह ऊपर दिए गए तीसरे बिंदु की बाधा को दूर कर देता है।

अब समाधान 1 लें और पेलोड को लूप के अंदर ले जाएँ:

कॉलमसेल्सभूमिका
09i = 9 (H का कॉलम)
1-3@ s !हॉल्ट गैजेट, समाधान 1 की तरह
4-8@@@@@पाँच आसन्न ट्रैम्पोलिन, इसलिए बॉडी ठीक 13 बार चलती है
9-21Hello, Worlä¡पेलोड, हर राउंड में निष्पादित होता है
22-271 ^ g P 1 +i कॉपी करें, प्राप्त करें, प्रिंट करें, बढ़ाएँ
28$लूप

एक राउंड की प्रक्रिया को समझें:

  1. PC @ श्रृंखला में कहीं उतरता है और पेलोड से होकर गुज़रता है। H e l l o, स्पेस और W o r l कुछ नहीं करते। पेलोड का , वह 0 पुश करता है जिसकी g को अपनी पंक्ति के रूप में आवश्यकता होती है। ä और ¡ कुछ नहीं करते।
  2. 1^ उस 0 के ऊपर i की प्रतिलिपि बनाता है, और g कॉलम i को प्राप्त करता है।
  3. P इसे प्रिंट करता है। अंतिम दो अक्षरों के लिए यह 0xE4 & 0x7F = 'd' और 0xA1 & 0x7F = '!' प्रिंट करता है।
  4. 1+, i को आगे बढ़ाता है, और $ श्रृंखला में वापस लौटता है।

समाधान 1 की तुलना में, तीन सेल गायब हो जाते हैं:

32 − 3 = 29। 13वें राउंड के बाद, कॉल स्टैक खुलकर गैजेट तक पहुँचता है और प्रोग्राम कॉलम 3 में स्थित ! पर रुक जाता है।

आउटपुट Hello, World!, कोई VM संदेश नहीं, 271 साइकिल, क्षेत्रफल 29।

🌐 अंतिम बाधा: जज तक बाइट्स पहुँचाना 🔗

पहला सबमिशन got: 'Hello, WorlC$' और 31 के स्कोर के साथ वापस आया। वेब फ़ॉर्म ने UTF-8 पोस्ट किया था, जिसने प्रत्येक विशेष अक्षर को दो बाइट्स (ä → C3 A4, ¡ → C2 A1) में बदल दिया था। 7 बिट्स में मास्क किए जाने पर, 0xC3 प्रिंट होता है C के रूप में और 0xA4 प्रिंट होता है $ के रूप में।

इसका समाधान ब्राउज़र से Latin-1 भिजवाना है, जहाँ इनमें से प्रत्येक अक्षर एक बाइट का होता है। चैलेंज पेज पर, मुझे DevTools कंसोल खोलना पड़ा और यह चलाना पड़ा:

document.querySelectorAll('form').forEach(
  f => f.acceptCharset = 'ISO-8859-1');
document.querySelector('textarea').value =
  "9@s!@@@@@Hello, Worl\u00e4\u00a11^gP1+$";

फिर सामान्य सबमिट बटन दबाएँ। जज Hello, World! प्रिंट करता है, और King of the Hill स्कोर 29 हो जाता है।


📊 स्कोरबोर्ड 🔗

#प्रोग्रामक्षेत्रफलक्या साफ-सुथरे ढंग से समाप्त होता है?
1Hello, World!%0@s!@@@@@ 01^gP1+$32✅
21H@e@l@l@o ,1 ^WgoPr2lsds!+$28❌ अतिरिक्त बाइट्स और कॉल स्टैक अंडरफ़्लो
3\2H@e@l@l@ox,g PW2o+r$ld!27❌ अतिरिक्त बाइट्स और कॉल स्टैक अंडरफ़्लो
4\2H@e@l@l@ox,g PWxo5rdl5d?!2+$30✅
59@s!@@@@@Hello, Worlä¡1^gP1+$29✅

💡 मुख्य निष्कर्ष 🔗


📚 मेरी निःशुल्क ई-बुक डाउनलोड करें 🔗

काउए की जीवनशैली का क्यूरेटेड ऑफ़लाइन संस्करण प्राप्त करें—🍏 स्वास्थ्य, 💰 धन, ❤️ प्रेम और 🧘 अर्थ को बेहतर बनाने के लिए एक व्यावहारिक मार्गदर्शिका।

काउए की जीवनशैली

काउए की जीवनशैली

📬 न्यूज़लेटर की सदस्यता लें 🔗

जब भी मैं बेहतर जीवन जीने पर नए निबंध, पुस्तक सारांश और व्यावहारिक गाइड प्रकाशित करूँ, तो सूचना प्राप्त करें। कोई स्पैम नहीं—कभी भी सदस्यता समाप्त करें।


💬 टिप्पणियाँ और चर्चा 🔗

क्या आपका कोई प्रश्न, दृष्टिकोण या सुझाव है? नीचे अपने विचार साझा करें। टिप्पणियाँ GitHub Discussions (विज्ञापन-मुक्त और स्पैम-मुक्त) द्वारा संचालित हैं—टिप्पणी करने या प्रतिक्रिया देने के लिए नीचे Sign in with GitHub पर क्लिक करें (निःशुल्क GitHub खाता बनाने में एक मिनट से भी कम समय लगता है)।



अंतिम अपडेट: 2 अक्टू॰ 2026.

अस्वीकरण (DISCLAIMER): इस साइट की सामग्री केवल सूचनात्मक और शैक्षिक उद्देश्यों के लिए है और यह चिकित्सा, मनोवैज्ञानिक, वित्तीय, निवेश, कर या कानूनी सलाह का गठन नहीं करती है। यहाँ प्रस्तुत विचार, संकलन और राय पूरी तरह से मेरे अपने हैं और मेरे नियोक्ता का प्रतिनिधित्व नहीं करते हैं। पुस्तकों, व्याख्यानों और लेखों के सारांश स्वतंत्र शैक्षिक टिप्पणियाँ हैं और उनके संबंधित लेखकों की बौद्धिक संपदा बने रहते हैं। संपादन, स्वरूपण और संश्लेषण में सहायता के लिए AI उपकरणों का उपयोग किया जा सकता है; यद्यपि सटीकता सुनिश्चित करने का हर संभव प्रयास किया जाता है, फिर भी त्रुटियाँ हो सकती हैं। गोपनीयता (PRIVACY): यह साइट वैकल्पिक न्यूज़लेटर सदस्यता (follow.it), टिप्पणियों (giscus / GitHub Discussions) और एम्बेडेड मीडिया (YouTube) के लिए तृतीय-पक्ष सेवाओं का उपयोग करती है, जो अपनी संबंधित गोपनीयता नीतियों के अनुसार आगंतुकों के IP पते और कुकीज़ को संसाधित कर सकती हैं।