थ्रोबैक फ्राइडे: मेरी ZX स्पेक्ट्रम बेसिक सूची को फिर से बनाएं


15

पहली प्रोग्रामिंग लैंग्वेज जो मैंने उजागर की थी वह सिनक्लेयर बेसिक थी । कई BASIC बोलियों की तरह, इसके लिए सभी सोर्स कोड लाइनों की आवश्यकता होती है ।

नतीजतन, GO TOकमांड का उपयोग मुहावरेदार था और दिए गए लाइन नंबर (कोई लेबल नहीं) के लिए कूदता है।

इसके अलावा एक संबंधित GO SUBकमांड है जिसका उपयोग अल्पविकसित फ़ंक्शन कॉल के रूप में किया जा सकता है। फिर, निष्पादन दिए गए लाइन नंबर पर कूदता है, लेकिन जब एक RETURNकमांड पहुंच जाता है, तो निष्पादन अगले निर्देश पर वापस कूदता है GO SUB

इसी प्रकार RUNकमांड दिए गए लाइन पर प्रोग्राम के निष्पादन को फिर से शुरू करेगा।

जिस किसी ने भी किसी भी समय एक लाइन-गिने हुए बेसिक दुभाषिया में समय बिताया है, उसने इसमें अंतराल के साथ नंबरिंग योजना का उपयोग करना सीख लिया होगा। यह इतना है कि कोड की नई लाइनें सम्मिलित करना आसान है। हालाँकि तब भी, आप अभी भी लगातार गिने लाइनों के बीच खुद को नई लाइनें डालने की जरूरत महसूस कर सकते हैं।


इनपुट के रूप में एक लाइन-क्रमांकित BASIC लिस्टिंग को देखते हुए, उसी प्रोग्राम को आउटपुट किया जाता है, लेकिन इसे फिर से सेट किया जाता है, जैसे कि लाइन नंबर 10 पर शुरू होते हैं और 10. के चरणों में वृद्धि होती है। इनपुट लिस्टिंग में कमांड GO TOया GO SUBकमांड हो सकते हैं , इसलिए इनसे जुड़े नंबर भी समायोजित किए जाने चाहिए।

  • GO TOऔर GO SUBकमांड या तो अपनी लाइनों पर या लाइनों के अंत में IF THENहैं। कहने के लिए इसकी तिजोरी ^(\d+) .*GO (TO|SUB) (\d+)$ऐसी रेखाओं से मेल खाने के लिए पर्याप्त है। उद्धरणों में इन आदेशों को अनदेखा किया जाना चाहिए।

  • RUNकमांड हमेशा अपनी तर्ज पर होंगे। इस स्थिति में एक पंक्ति संख्या वैकल्पिक है। यदि यह गायब है, तो दुभाषिया बस कार्यक्रम के शीर्ष पर शुरू होता है।

  • यदि कोई GO TO, GO SUBया RUNकमांड एक गैर-मौजूद रेखा का संदर्भ देता है, तो यह बजाय अगली परिभाषित रेखा पर कूद जाएगा। आपकी प्रविष्टि को इससे निपटने की आवश्यकता है और यह सुनिश्चित करना है कि इस तरह की कोई भी रेखा संदर्भ तय हो, इसलिए वे सही रेखा की ओर इशारा करते हैं। यदि प्रोग्राम के अंत के बाद एक पंक्ति संख्या इन आदेशों में दी गई है, तो व्यवहार अपरिभाषित हो सकता है।

  • लाइन नंबर हमेशा सकारात्मक पूर्णांक 1 से 9999 (मैनुअल के अनुसार) होगा। इसका मतलब है कि इनपुट प्रोग्राम में कभी भी 999 से अधिक लाइनें नहीं होंगी।

  • इनपुट लाइनों को हमेशा संख्यात्मक रूप से आरोही क्रम में क्रमांकित किया जाएगा।

  • इस चुनौती के प्रयोजनों के लिए, इनपुट लिस्टिंग में केवल मुद्रण योग्य ASCII शामिल होगा। आपको ZX वर्ण सेट के बारे में चिंता करने की आवश्यकता नहीं है। कि कहा है, अगर आपकी प्रविष्टि वास्तव में ZX बुनियादी में लिखा है या विधानसभा मशीन कोड Z80 उचित / (और देखते हैं emulators बाहर वहाँ ), तो आप के लिए अपने इनपुट में एन्कोड करने के लिए चुन सकते ZX वर्ण सेट के बजाय।

  • आप किसी भी रेंबरी लाइब्रेरी या उपयोगिताओं का उपयोग नहीं कर सकते हैं जो विशेष रूप से इस उद्देश्य के लिए सिलवाया गया है।

उदाहरण इनपुट:

1 REM "A rearranged guessing game"
2 INPUT A: CLS
3 INPUT "Guess the number ", B
10 IF A=B THEN PRINT "Correct": STOP
100 IF A<B THEN GO SUB 125
120 IF A>B THEN GO SUB 122
121 GO TO 3
125 PRINT "Try again"
126 RETURN
127 REM "An example of GO TO 7 and GO SUB 13 in quotes"

उदाहरण आउटपुट:

10 REM "A rearranged guessing game"
20 INPUT A: CLS
30 INPUT "Guess the number ", B
40 IF A=B THEN PRINT "Correct": STOP
50 IF A<B THEN GO SUB 80
60 IF A>B THEN GO SUB 80
70 GO TO 30
80 PRINT "Try again"
90 RETURN
100 REM "An example of GO TO 7 and GO SUB 13 in quotes"

मैं एक ZX BASIC मैनुअल से लिंक करना चाहता था। मुझे जो सबसे अच्छा लगता है वह है http://www.worldofspectrum.org/ZXBasicManual/index.html। लेकिन यह एक मृत कड़ी प्रतीत होती है। Wayback मशीन की एक प्रति है


7
5000 वां प्रश्न पूछने पर भी बधाई!
FryAmTheEggman

1
नॉस्टैल्जिया समय - मेरा पहला पीसी एक स्पेक्ट्रम 48K था और मेरे पहले विधानसभा कार्यक्रमों में से एक
रेननर

2
@ edc65 क्या आपके पास अभी भी अपना रेनम्बर असेंबली कोड है? यदि ऐसा है तो आप इसे उत्तर के रूप में पोस्ट करने के लिए बहुत स्वागत करेंगे!
डिजिटल ट्रामा

1
परीक्षण मामले में एक स्ट्रिंग शाब्दिक में कम से कम एक गोटो / गोसुब शामिल होना चाहिए।
पीटर टेलर

1
मैंने एक उल्लेख पाया: ZX81 में GOTO और GOSUBs की गणना करने की अनुमति देता हैGOTO 100 + A*10 , और एक संख्यात्मक अभिव्यक्ति (स्थिरांक के लिए कोई प्रतिबंध नहीं) के रूप में ZX स्पेक्ट्रम मैनुअल सूचियों के परिशिष्ट C। GO TOयहाँ ZX80 और ZX81 पर गणना के गुणों की चर्चा है GOTO। BTW, मुझे पता नहीं क्यों अंतरिक्ष स्पेक्ट्रम संस्करण में जोड़ा गया था।
टोबी स्पाइट

जवाबों:


5

जावास्क्रिप्ट (ईएस 6) 177

संपादित करें जोड़ा गया (महंगा) अगली मान्य लाइन नंबर के लिए स्कैन

l=>l.split`
`.map((x,i)=>([,n,t]=x.match(/(\d+)(.*)/),l[n]=10*-~i,t),l=[]).map((x,i)=>10*-~i+x.replace(/(UN |GO TO |UB )(\d+)$/,(a,b,c)=>(l.some((v,i)=>i<c?0:a=b+v),a))).join`
`

परीक्षा

f=l=>
  l.split`\n`
  .map((x,i)=>([,n,t]=x.match(/(\d+)(.*)/),l[n]=10*-~i,t),l=[])
  .map((x,i)=>10*-~i+x.replace(/(UN |GO TO |UB )(\d+)$/,(a,b,c)=>(l.some((v,i)=>i<c?0:a=b+v),a)))
  .join`\n`
        
//TEST
console.log=x=>O.textContent+=x+'\n'
  
test=`1 REM "A rearranged guessing game"
2 INPUT A: CLS
3 INPUT "Guess the number ", B
10 IF A=B THEN PRINT "Correct": STOP
100 IF A<B THEN GO SUB 125
120 IF A>B THEN GO SUB 122
121 GO TO 3
125 PRINT "Try again"
126 RETURN`
console.log(test+'\n\n'+f(test))
<pre id=O></pre>


1
अछा लगता है। मेरा +1 खड़ा है :)
डिजिटल ट्रामा

2

पर्ल 6, 147 145 144 142 बाइट्स

{my%a;.trans(/^^(\d+)/=>{%a{$0}=$+=10}).trans(/:s<!after \"\N*>(UN |GO TO |UB )(\d+)<!before \N*\">/=>{$0~%a{%a.keys».Num.grep(*>=$1).min}})}

यह शायद थोड़ा और नीचे गोल्फ हो सकता है।

विस्तारित

my &f = -> $s { 
    my %line-map; # This will map the old line numbers to the new ones

    $s.trans(/^^(\d+)/                    # This .trans creates the line number map
             => { %line-map{$0} = $+=10 } # as well as replaces the actual line numbers
            )\
      # This .trans replaces all the line numbers for each GO TO, GO SUB, RUN
      .trans(/:s<!after \"\N*>(UN |GO TO |UB )(\d+)<!before \N*\">/ 
             => {$0 ~ %line-map{%line-map.keys».Num.grep(*>=$1).min} } 
            )
}

विधि का उपयोग करने का कोई कारण नहीं .min। का उपयोग {min %line-map.keys».Num.grep:*>=$1करने के बजाय
Ven

1

एप्लीकेशन के लिए विजुअल बेसिक, 288 बाइट्स

मैं एक बुनियादी बोली में समाधान देने का विरोध नहीं कर सका। संभवतः मामूली बदलाव के साथ विजुअल बेसिक 6 / .NET या अन्य आधुनिक वेरिएंट के साथ काम करता है।

Sub n(t,a)
f=Chr(10)
u=Chr(0)
Open t For Input As 1
a=f &Input(LOF(1),1)&f
Close
j=10
For i=1 To 9999
q=f &j &u
g=" GO TO "
w=i &f
m=j &f
a=Replace(Replace(Replace(Replace(a,g &w,g &m),f &i &" ",q),"B "&w,"B "&m),"UN "&w,"UN "&m)
If InStr(1,a,q)Then j=j+10
Next
a=Replace(a,u," ")
End Sub

मैंने संक्षिप्तता के लिए बहुत सारे एक-अक्षर वाले चर का उपयोग किया। इसके अलावा, मैंने सभी अनावश्यक व्हाट्सएपों को दबा दिया (VBE उन्हें स्वचालित रूप से आयात पर विस्तारित करता है)। बाइट की गिनती अंतिम .BAS फ़ाइल के लिए होती है, जिसमें नई पंक्ति के रूप में CHR (10) होता है।

सबरूटीन, जिसे VBE तत्काल विंडो से मंगाया जा सकता है, एक सिनक्लेयर बेसिक प्रोग्राम खोलता है (पहला पैरामीटर एक ASCII फ़ाइल का मार्ग है - CHR (10) के साथ न्यूलाइन के रूप में - प्रोग्राम से युक्त), रेनम्बर लाइन्स और वेरिएंट वेरिएबल के लिए परिणाम लिखें (दूसरा पैरामीटर)।

विचार आरोही क्रम, और हर एक के लिए, साथ ही एक बार सभी मिलान लाइन नंबर पर की जगह हर संभव स्रोत लाइन नंबर की पुनरावृति करने के लिए है, GO TO, GO SUBऔर RUNअगले उपलब्ध लक्ष्य लाइन संख्या के साथ संदर्भ। इस दृष्टिकोण का उपयोग करके हमें किसी भी प्रकार की अनुवाद तालिका की आवश्यकता नहीं है। जब भी सोर्स लाइन नंबर में मैच पाया जाता है, तो लक्ष्य रेखा संख्या बढ़ाई जाती है, इसलिए "गलत" लाइन संदर्भ स्वचालित रूप से अगले वैध संख्या में समायोजित हो जाते हैं। Newline वर्णों का उपयोग स्टार्ट-एंड-एंड-लाइन और एक CHR (0) के मार्कर के रूप में किया जाता है - प्रोग्राम में कभी भी इसका उपयोग नहीं किया जाता है क्योंकि यह प्रिंट करने योग्य नहीं है - एक ही बार में एक ही लाइन को कई बार रिरन करने से बचने के लिए, अस्थायी मार्कर के रूप में उपयोग किया जाता है।

कुछ टिप्पणी:

  • संक्षिप्तता के लिए, हम जंपिंग स्टेटमेंट के साथ मैच के लिए छोटे संभव स्ट्रिंग का उपयोग करते हैं। अपने खोज स्ट्रिंग्स पर एंड-ऑफ-लाइन का उपयोग करते हुए हम उद्धृत ऑक्युपेरेंस या उपयोगकर्ता कार्यों (जो हमेशा सिंक्लेयर में कोष्ठक का उपयोग करते हैं) को शामिल करने के जोखिम में नहीं चलते हैं। निर्माण GO TOकी वजह से एक बड़ी स्ट्रिंग की आवश्यकता होती है FOR ... TO(जैसे तुलना 50 FOR X=AGO TO 100और 50 GO TO 100)

  • कोड फॉर्म GO TO200(व्हाट्सएप के बिना) में बयानों का समर्थन नहीं करता है , हालांकि जेडएक्स मैनुअल का अर्थ है कि यह कई उदाहरणों पर मान्य कोड है (इससे निपटने के लिए एक दर्जन से अधिक बाइट खर्च होंगे)।

  • कोड शुरुआत में एक नई रेखा और कार्यक्रम के अंत में एक और जोड़ता है। मैं अंत में इसे साफ कर सकता हूं (एक दर्जन से अधिक बाइट्स) लेकिन यह आंकड़ा कि ZX शायद खाली लाइनों को नजरअंदाज करेगा।

नीचे, अधिक पठनीय संस्करण:

Sub Renumber(ByVal ProgramPath As String, ByRef Program As Variant)

    Open ProgramPath For Input As #1
    Program = Chr(10) & Input(LOF(1), 1) & Chr(10)
    Close

    NewNumber = 10
    For OldNumber = 1 To 9999
        Program = Replace(Program, " GO TO" & OldNumber & Chr(10), " GO TO" & NewNumber & Chr(10)) 'self-explaining
        Program = Replace(Program, Chr(10) & OldNumber & " ", Chr(10) & NewNumber & Chr(0)) 'matches line number (and replaces whistespace with Chr(0) to avoid re-replacing
        Program = Replace(Program, "B " & OldNumber & Chr(10), "B " & NewNumber & Chr(10)) 'matches GO SUB
        Program = Replace(Program, "UN " & OldNumber & Chr(10), "UN " & NewNumber & Chr(10)) 'matches RUN
        If InStr(1, Program, Chr(10) & NewNumber & Chr(0)) Then NewNumber = NewNumber + 10 'if there is such a line, increment NewNumber
Next
Program = Replace(Program, Chr(0), " ") 'replace back Chr(0) with whitespace
End Sub

BTW, एक QBasic समाधान ज्यादा लंबा होगा, क्योंकि QBasic में स्ट्रिंग-रिप्लेसमेंट फंक्शन नहीं है, जहां तक ​​मुझे याद है।
DLosc

मुझे लगता है कि आप सही हैं ... इस बारे में भूल गए
dnep

1

पिप -rn , 63 बाइट्स

Ygn:#{_<aFIy}*t+tgR`(RUN|GO (SUB|TO)) (\d+)$`{b.s.(nd)}R`^\d+`n

इसे ऑनलाइन आज़माएं!

व्याख्या

सेट अप

-rझंडा स्थानीय चर में लाइनों की सूची के रूप में stdin और यह भंडार के सभी पढ़ता है g। ग्लोबल वैरिएबल tको 10 से प्रीइंस्टीट्यूशनल किया जाता है, और ग्लोबल वैरिएबल sको प्री-कंस्ट्रक्टिफाई किया जाता है " "

Yg

gवैश्विक चर में लाइनों की सूची को यैंक करता है y, ताकि यह उस फ़ंक्शन के अंदर उपलब्ध हो जिसे हम परिभाषित करने वाले हैं।

लाइन नंबर अनुवाद समारोह

हम एक फ़ंक्शन का निर्माण करते हैं जो मूल संख्या योजना (किसी गैर-मौजूद व्यक्ति सहित) में किसी भी पंक्ति संख्या से नई क्रमांक योजना में संबंधित पंक्ति संख्या में मैप करता है।

मान लीजिए कि हमारे पास ये लाइनें हैं:

1 INPUT A
4 PRINT A
9 IF A=1 THEN GO TO 3

हम 1 से 10, 2-4 से 20, और 5-9 से 30 तक का नक्शा बनाना चाहते हैं। यदि हमारे पास मूल लाइन नंबरों ( [1; 4; 9]) की सूची है, तो हम यह पता लगाने के लिए फ़िल्टर ऑपरेशन का उपयोग कर सकते हैं कि इनमें से कितने नंबर कम हैं उस पंक्ति संख्या की तुलना में जिसे हम परिवर्तित करने का प्रयास कर रहे हैं। उस परिणाम को 10 से गुणा करें और 10 जोड़ें, और हमारे पास वांछित उत्तर है।

उदाहरण के लिए, 9 को परिवर्तित करते समय, दो पंक्ति संख्याएँ (1 और 4) 9 से कम होती हैं। 2 * 10 + 10 30 देता है। 3 को परिवर्तित करते समय, एक पंक्ति संख्या (1) 3. 3. 1 * 10 + 10 से कम होती है। 20 देता है।

यहां कोड है (पढ़ने में आसान होने के लिए थोड़ा संशोधित):

n:{#(_<aFIy)*t+t}
  {             }  Lambda function with parameter a:
        FIy         Filter y (the list of program lines) for
     _<a             lines that are numerically less than a
                    (In a numeric context, only the first run of digits on the line is considered)
   #(      )        Number of items in the filtered list
            *t+t    Times 10, plus 10
n:                 Assign that function to global variable n

सबसे पहले प्रतिस्थापन: GO TO, GO SUB, औरRUN

कार्यक्रम के बाकी एक एकल अभिव्यक्ति है जो gरेगेक्स प्रतिस्थापन के एक जोड़े को लेती है और करती है (जो वेक्टर करती है, प्रत्येक पंक्ति में लागू होती है g)।

यहाँ पहला प्रतिस्थापन है:

g R `(RUN|GO (SUB|TO)) (\d+)$` {b.s.(nd)}

Regex किसी भी संख्या से मेल खाता है RUN, GO SUBऔर GO TOउसके बाद एक नंबर आता है, उसके बाद पंक्ति समाप्त होती है। यह सुनिश्चित करता है कि यह तार के अंदर मेल नहीं खाता है, और न ही यह RUNबिना लाइन नंबर के मेल खाता है ।

कब्जा करने वाले समूहों का क्रम महत्वपूर्ण है। पहले समूह आदेश (में से एक कब्जा RUN, GO SUBया GO TO)। दूसरा समूह, यदि उपयोग किया जाता है, SUBया तो कैप्चर करता है या TO। हमें इस हिस्से को पकड़ने की जरूरत नहीं है, लेकिन एक गैर-कैप्चरिंग समूह को अतिरिक्त बाइट्स की आवश्यकता होगी। फिर तीसरा समूह लाइन नंबर को कैप्चर करता है।

हम प्रतिस्थापन के लिए कॉलबैक फ़ंक्शन का उपयोग करते हैं। पिप में कॉलबैक कार्यों के साथ, पूरे मैच पहला तर्क है a, और आदेश में कैप्चर समूहों बाद तर्क हैं b, c, d, और e। इसलिए हमारे पास पहले समूह में कमांड है, जो bतीसरे समूह में जाता है , और लाइन नंबर तीसरे समूह में जाता है d। हमारे द्वारा किए जाने वाले एकमात्र परिवर्तन को हमारे रूपांतरण फ़ंक्शन के माध्यम से लाइन नंबर पास करना है, जिसे लिस्प-शैली कहा जाता है (nd):। फिर हम एक साथ bऔर एक स्थान को समेटते हैं और इसे वापस करते हैं।

दूसरा प्रतिस्थापन: लाइन नंबर

सभी कि कन्वर्ट करने के लिए छोड़ दिया है लाइनों की शुरुआत में लाइन नंबर है।

(...) R `^\d+` n

रेगेक्स एक पंक्ति की शुरुआत में अंकों की एक रन से मेल खाता है। फिर से हम एक कॉलबैक फ़ंक्शन का उपयोग करते हैं; इस बार, रूपांतरण फ़ंक्शन nअपने आप में पर्याप्त है, क्योंकि पूरा मैच (पहला तर्क a) वह संख्या है जिसे हम परिवर्तित करना चाहते हैं।

चूँकि यह कार्यक्रम की अंतिम अभिव्यक्ति है, पिप परिणाम को दर्शाता है। -nझंडा नई-पंक्तियों के साथ परिणाम सूची अलग करती है।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.