एक Minsky रजिस्टर मशीन का अनुकरण करें (I)


26

कई औपचारिकताएं हैं, इसलिए जब आप अन्य स्रोतों को उपयोगी पा सकते हैं, तो मुझे यह स्पष्ट रूप से निर्दिष्ट करने की उम्मीद है कि वे आवश्यक नहीं हैं।

आरएम में एक परिमित राज्य मशीन और एक पंजीकृत संख्या का नाम रजिस्टर होता है, जिनमें से प्रत्येक में एक गैर-नकारात्मक पूर्णांक होता है। शाब्दिक इनपुट में आसानी के लिए इस कार्य के लिए आवश्यक है कि राज्यों का भी नाम हो।

तीन प्रकार के राज्य हैं: वेतन वृद्धि और वेतन वृद्धि, जो दोनों एक विशिष्ट रजिस्टर का संदर्भ देते हैं; और समाप्त करें। एक वेतन वृद्धि राज्य अपने रजिस्टर को बढ़ाता है और अपने एक उत्तराधिकारी को नियंत्रण देता है। एक गिरावट राज्य में दो उत्तराधिकारी होते हैं: यदि उसका रजिस्टर गैर-शून्य है तो वह इसे घटाता है और पहले उत्तराधिकारी को नियंत्रण देता है; अन्यथा (अर्थात रजिस्टर शून्य है) यह बस दूसरे उत्तराधिकारी के लिए नियंत्रण से गुजरता है।

प्रोग्रामिंग भाषा के रूप में "स्पष्टता" के लिए, समाप्त होने वाली स्थिति प्रिंट करने के लिए एक कठोर-कोडित स्ट्रिंग लेती है (ताकि आप असाधारण समाप्ति का संकेत कर सकें)।

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

line       ::= inc_line
             | dec_line
inc_line   ::= label ' : ' reg_name ' + ' state_name
dec_line   ::= label ' : ' reg_name ' - ' state_name ' ' state_name
state_name ::= label
             | '"' message '"'
label      ::= identifier
reg_name   ::= identifier

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

इनपुट की अंतिम पंक्ति, जो प्रारंभिक रजिस्टर मान देती है, पहचानकर्ता = अंतर असाइनमेंट की एक अलग-अलग सूची है, जो गैर-रिक्त होनी चाहिए। यह आवश्यक नहीं है कि यह प्रोग्राम में नामित सभी रजिस्टरों को इनिशियलाइज़ करता है: जो भी इनिशियलाइज़ नहीं हैं उन्हें 0 मान लिया जाता है।

आपके कार्यक्रम को इनपुट पढ़ना चाहिए और आरएम का अनुकरण करना चाहिए। जब यह एक समाप्त अवस्था में पहुंचता है तो यह संदेश, एक नई पंक्ति और फिर सभी रजिस्टरों के मूल्यों (किसी भी सुविधाजनक, मानव-पठनीय, प्रारूप और किसी भी क्रम में) का उत्सर्जन करना चाहिए।

नोट: औपचारिक रूप से रजिस्टरों को अनबाउंड पूर्णांक रखना चाहिए। हालाँकि, आप चाहें तो मान सकते हैं कि किसी भी रजिस्टर का मूल्य कभी भी 2 ^ 30 से अधिक नहीं होगा।

कुछ सरल उदाहरण

ए + = बी, ए = 0
s0 : a - s1 "Ok"
s1 : b + s0
a=3 b=4

अपेक्षित परिणाम:

Ok
a=0 b=7
बी + = ए, टी = 0
init : t - init d0
d0 : a - d1 a0
d1 : b + d2
d2 : t + d0
a0 : t - a1 "Ok"
a1 : a + a0
a=3 b=4

अपेक्षित परिणाम:

Ok
a=3 b=7 t=0
पेचीदा-टू-पार्स मशीनों के लिए परीक्षण के मामले
s0 : t - s0 s1
s1 : t + "t is 1"
t=17

अपेक्षित परिणाम:

t is 1
t=1

तथा

s0 : t - "t is nonzero" "t is zero"
t=1

अपेक्षित परिणाम:

t is nonzero
t=0

एक अधिक जटिल उदाहरण

DailyWTF की जोसेफस समस्या कोड चुनौती से लिया गया। इनपुट n (सैनिकों की संख्या) और k (अग्रिम) और आउटपुट में r (शून्य अनुक्रमित) उस व्यक्ति की स्थिति है जो जीवित रहता है।

init0 : k - init1 init3
init1 : r + init2
init2 : t + init0
init3 : t - init4 init5
init4 : k + init3
init5 : r - init6 "ERROR k is 0"
init6 : i + init7
init7 : n - loop0 "ERROR n is 0"
loop0 : n - loop1 "Ok"
loop1 : i + loop2
loop2 : k - loop3 loop5
loop3 : r + loop4
loop4 : t + loop2
loop5 : t - loop6 loop7
loop6 : k + loop5
loop7 : i - loop8 loopa
loop8 : r - loop9 loopc
loop9 : t + loop7
loopa : t - loopb loop7
loopb : i + loopa
loopc : t - loopd loopf
loopd : i + loope
loope : r + loopc
loopf : i + loop0
n=40 k=3

अपेक्षित परिणाम:

Ok
i=40 k=3 n=0 r=27 t=0

यह कार्यक्रम एक चित्र के रूप में, उन लोगों के लिए जो नेत्रहीन सोचते हैं और इसे वाक्यविन्यास को समझना उपयोगी होगा: जोसेफस समस्या RM

यदि आप इस गोल्फ का आनंद लेते हैं, तो अगली कड़ी देखें


क्या इनपुट स्टड से, किसी फाइल से, या किसी अन्य जगह से आता है?
केविन ब्राउन

@ बास, स्टड से।
पीटर टेलर

आपको मुद्दों को संभालने के लिए निम्नलिखित कठिन मामलों के साथ कुछ परीक्षण मामलों को जोड़ना चाहिए: 1) रिक्त स्थान के साथ संदेश, 2) समान संकेत वाले संदेश, 3) inc_line में संदेश, 4) एक dec_line के पहले राज्य में संदेश, 5) रिक्त स्थान में 5) संदेश मामलों 3 और 4.
माउंटनवार्क

व्याकरण में एक त्रुटि है: dec_line में दो state_name प्रविष्टियों के बीच शाब्दिक स्थान होना चाहिए। यह भी स्पष्ट नहीं है कि यदि आप लोगों को इनपुट में टोकन के बीच कई रिक्त स्थान स्वीकार करने की आवश्यकता है।
माउंटन व्यूमार्क

2
@ पेटर: एक बहुत भावपूर्ण कोड-गोल्फ के लिए विनिर्देशन और पैंतरेबाज़ी के कमरे के अच्छे संतुलन के साथ! यहां ज्यादातर सवाल बहुत पतले थे।
माउंटनवार्क मार्क

जवाबों:


10

पर्ल, 166

@p=<>;/=/,$_{$`}=$' for split$",pop@p;$o='\w+';(map{($r
,$o,$,,$b)=$'=~/".*?"|\S+/g if/^$o :/}@p),$_=$o=($_{$r}
+=','cmp$o)<0?do{$_{$r}=0;$b}:$,until/"/;say for eval,%_

साथ चलाना perl -M5.010 file

यह बेतहाशा अलग शुरू हुआ, लेकिन मुझे डर है कि यह रूबी समाधान के साथ कई क्षेत्रों में अंत तक परिवर्तित हो गया। लगता है कि रूबी का फायदा "नो सिगिल" है, और पर्ल का "बेहतर रेगेक्स इंटीग्रेशन"।

यदि आप पर्ल नहीं पढ़ते हैं, तो सराय से थोड़ा सा विवरण:

  • @p=<>: पूरी मशीन विवरण पढ़ें @p
  • /=/,$_{$`}=$' for split$",pop@p: अंतिम मशीन विवरण पंक्ति में प्रत्येक ( for) असाइनमेंट ( split$") के लिए @p, बराबर चिह्न का पता लगाएं ( /=/) तो $'hask %_कुंजी के लिए मान असाइन करें$`
  • $o='\w+': प्रारंभिक राज्य पर्ल रेगेक्स "शब्द वर्ण" से मेल खाने वाला पहला होगा
  • until/"/: लूप जब तक हम एक समाप्ति स्थिति तक नहीं पहुंच जाते:
    • map{($r,$o,$,,$b)=$'=~/".*?"|\S+/g if/^$o :/}@p: मशीन विवरण पर लूप @p: जब हम वर्तमान स्थिति से मेल खाते हुए लाइन पर होते हैं ( if/^$o :/), टोकेनाइज ( /".*?"|\S+/g) बाकी लाइन $'से चर तक ($r,$o,$,,$b)। ट्रिक: एक ही वैरिएबल $oयदि शुरू में लेबल नाम के लिए और बाद में ऑपरेटर के लिए उपयोग किया जाता है। जैसे ही लेबल मेल खाता है, ऑपरेटर इसे ओवरराइड करता है, और एक लेबल के रूप में (यथोचित) का नाम + या - नहीं किया जा सकता है, यह फिर से शुरू नहीं होता है।
    • $_=$o=($_{$r}+=','cmp$o)<0?do{$_{$r}=0;$b}:$,:
      - लक्ष्य रजिस्टर को $_{$r}ऊपर या नीचे समायोजित करें (ASCII मैजिक: ','cmp'+'1 है जबकि ','cmp'-'-1 है);
      - यदि परिणाम नकारात्मक है ( <0?, केवल के लिए हो सकता है -)
      - तो 0 पर रहें ( $_{$r}=0) और दूसरा लेबल वापस करें $b;
      - और फिर पहले (संभवतः एकमात्र) लेबल पर लौटें$,
    • BTW, यह $,इसके बजाय $aइसलिए इसे untilबीच में कोई व्हाट्सएप के साथ अगले टोकन से चिपकाया जा सकता है ।
  • say for eval,%_: डंप रिपोर्ट ( eval) और रजिस्टर में सामग्री%_

आपको वास्तव में बृहदान्त्र की आवश्यकता नहीं है /^$o :/। अकेले यह सुनिश्चित करने के लिए पर्याप्त है कि आप केवल लेबल देख रहे हैं।
लोजैकर

@Lowjacker मुझे यह निर्धारित करने की आवश्यकता नहीं है कि मैं सही लेबल पर हूं, लेकिन मुझे इसे बाहर रखने की आवश्यकता है $'। यह रेगेक्स में एक चरित्र है, यह $c,बाहर से खाते के लिए तीन होगा । वैकल्पिक रूप से कुछ बड़े अभी तक टोकन रेगेक्स में बदल जाते हैं।
JB

10

पायथन + सी, 466 वर्ण

बस मनोरंजन के लिए, एक पायथन प्रोग्राम जो आरएम प्रोग्राम को सी पर संकलित करता है, फिर सी को संकलित करता है और चलाता है।

import sys,os,shlex
G=shlex.shlex(sys.stdin).get_token
A=B=''
C='_:'
V={}
J=lambda x:'goto '+x+';'if'"'!=x[0]else'{puts('+x+');goto _;}'
while 1:
 L,c=G(),G()
 if''==c:break
 if':'==c:
  v,d=G(),G()
  V[v]=1;B+=L+c+v+d+d+';'
  if'+'==d:B+=J(G())
  else:B+='if('+v+'>=0)'+J(G())+'else{'+v+'=0;'+J(G())+'}'
 else:A+=L+c+G()+';'
for v in V:C+='printf("'+v+'=%d\\n",'+v+');'
open('C.c','w').write('int '+','.join(V)+';main(){'+A+B+C+'}')
os.system('gcc -w C.c;./a.out')

3
यदि रजिस्टरों में ' main', ' if' आदि जैसे नाम हों तो यह काम नहीं करेगा
NABb

1
@ नब: बज़किल। मैं इसे सही स्थानों पर अंडरस्कोर उपसर्गों को जोड़ने के लिए पाठक पर छोड़ता हूं।
कीथ रान्डेल

6

हास्केल, 444 अक्षर

(w%f)(u@(s,v):z)|s==w=(s,f+v):z|t=u:(w%f)z
(w%f)[]=[(w,f)]
p#(a:z)|j==a=w p++[j]&z|t=(p++[a])#z;p#[]=w p
p&(a:z)|j==a=p:""#z|t=(p++[a])&z
c x=q(m!!0)$map((\(s,_:n)->(s,read n)).break(=='=')).w$last x where
 m=map(""#)$init x
 q[_,_,r,"+",s]d=n s$r%1$d
 q[_,_,r,_,s,z]d|maybe t(==0)(lookup r d)=n z d|t=n s$r%(-1)$d
 n('"':s)d=unlines[s,d>>=(\(r,v)->r++'=':shows v" ")]
 n s d=q(filter((==s).head)m!!0)d
main=interact$c.lines
t=1<3;j='"';w=words

यार, यह मुश्किल था! उनमें रिक्त स्थान के साथ संदेशों की उचित हैंडलिंग 70 से अधिक वर्णों की होती है। आउटपुट स्वरूपण अधिक "मानव पठनीय" होने के लिए, और उदाहरणों से मेल खाते हैं एक और 25 की लागत।


  • संपादित करें: (४ ९: -> ४2२) विभिन्न छोटे-छोटे अस्तर, और कुछ @ फुजेनकल के सुझाव
  • संपादित करें: (482 -> 453) रजिस्टरों के लिए वास्तविक संख्याओं का उपयोग करके वापस स्विच करें; कई गोल्फ चालें लागू
  • संपादित करें: (453 -> 444) आउटपुट स्वरूपण और प्रारंभिक मूल्य पार्सिंग

मैं हास्केल को नहीं जानता, इसलिए मैं सभी वाक्यविन्यास को अस्वीकार नहीं कर सकता, लेकिन मैं यह देखने के लिए पर्याप्त व्याख्या कर सकता हूं कि आप रजिस्टर सामग्री के लिए सूचियों का उपयोग कर रहे हैं। मुझे कहना चाहिए कि मुझे आश्चर्य है कि यह ints का उपयोग करने से कम है।
पीटर टेलर

whereअर्धविराम द्वारा अलग की गई एक पंक्ति में स्थानीय बाइंडिंग लगाने से आप 6 वर्णों को बचा सकते हैं। और मुझे लगता है कि आप क्रिया को qबदलकर परिभाषा में कुछ चार्ट को बचा सकते हैं अगर-तो-फिर एक पैटर्न गार्ड को।
फ़ूजएक्सएक्सएल

और यह भी: बस आँख बंद करके मान लें कि तीसरा मान "-"परिभाषा में है qऔर इसके बजाय एक अंडरस्कोर का उपयोग करें।
फ़ूजएक्सएक्सएल

मुझे लगता है, आप लाइन 8 को बदलकर एक और चार बचा सकते हैं q[_,_,r,_,s,z]d|maybe t(==0)$lookup r d=n z d|t=n s$r%(-1)$d। लेकिन वैसे भी, यह कार्यक्रम बहुत अच्छा है।
19 दिसंबर को फ्यूजेंकल

आप lexप्रस्तावना से लाभ उठाकर पार्सिंग कोड को काफी छोटा कर सकते हैं । उदाहरण के लिए कुछ ऐसा है जो f[]=[];f s=lex s>>= \(t,r)->t:f rउद्धृत तारों को सही ढंग से संभालने के दौरान टोकन में एक रेखा को विभाजित करेगा।
हमार

6

रूबी 1.9, 214 212 211 198 195 192 181 175 173 175

*s,k=*$<
a,=s
b=Hash.new 0
eval k.gsub /(\w+)=/,';b["\1"]='
loop{x,y,r,o,t,f=a.scan /".*?"|\S+/
l=(b[r]-=o<=>?,)<0?(b[r]=0;f):t
l[?"]&&puts(eval(l),b)&exit
a,=s.grep /^#{l} /}

मुझे उम्मीद है कि यह एक दूसरे के लेबल उपसर्गों पर विफल होगा। विचार?
जेबी

मैं इसे उदाहरण के अलावा किसी अन्य मामले के साथ काम करने के लिए प्रतीत नहीं कर सकता। इसमें गलत क्या है ?
जेबी

मुझे लगता है कि अब यह तय हो गया है।
लॉजैकर

आह, बहुत बेहतर। धन्यवाद।
जेबी

3

डेल्फी, 646

डेल्फी बंटवारे के तार और सामान के संबंध में बहुत अधिक पेशकश नहीं करता है। सौभाग्य से, हमारे पास सामान्य संग्रह हैं, जो थोड़ी मदद करता है, लेकिन यह अभी भी एक बड़ा समाधान है:

uses SysUtils,Generics.Collections;type P=array[0..99]of string;Y=TDictionary<string,P>;Z=TDictionary<string,Int32>;var t:Y;l,i:string;j,k:Int32;q:P;u:Z;v:TPair<string,Int32>;begin t:=Y.Create;repeat if i=''then i:=q[0];t.Add(q[0],q);ReadLn(l);for j:=0to 6do begin k:=Pos(' ',l+' ');q[j]:=Copy(l,1,k-1);Delete(l,1,k)end;until q[1]<>':';u:=Z.Create;j:=0;repeat k:=Pos('=',q[j]);u.Add(Copy(q[j],1,k-1),StrToInt(Copy(q[j],k+1,99)));Inc(j)until q[j]='';repeat q:=t[i];i:=q[4];u.TryGetValue(q[2],j);if q[3]='+'then Inc(j)else if j=0then i:=q[5]else Dec(j);u.AddOrSetValue(q[2],j)until i[1]='"';WriteLn(i);for v in u do Write(v.Key,'=',v.Value,' ')end.

यहां इंडेंटेड और कमेंटेड वर्जन:

uses SysUtils,Generics.Collections;
type
  // P is a declaration line, offsets:
  // 0 = label
  // 1 = ':'
  // 2 = register
  // 3 = operation ('-' or '+')
  // 4 = 1st state (or message)
  // 5 = 2nd state (or message)
  P=array[0..99]of string;
  // T is a dictionary of all state lines :
  Y=TDictionary<string,P>;
  // Z is a dictionary of all registers :
  Z=TDictionary<string,Int32>;
var
  t:Y;
  l,
  i:string;
  j,
  k:Int32;
  q:P;
  u:Z;
  v:TPair<string,Int32>;
begin
  // Read all input lines :
  t:=Y.Create;
  repeat
    // Put all lines into a record
    if i=''then i:=q[0];
    t.Add(q[0],q);
    // Split up each input line on spaces :
    ReadLn(l);
    for j:=0to 6do
    begin
      k:=Pos(' ',l+' ');
      q[j]:=Copy(l,1,k-1);
      Delete(l,1,k)
    end;
    // Stop when there are no more state transitions :
  until q[1]<>':';
  // Scan initial registers :
  u:=Z.Create;
  j:=0;
  repeat
    k:=Pos('=',q[j]);
    // Add each name=value pair to a dictionary :
    u.Add(Copy(q[j],1,k-1),StrToInt(Copy(q[j],k+1,99)));
    Inc(j)
  until q[j]='';
  // Execute the state machine :
  repeat
    q:=t[i];
    i:=q[4];
    u.TryGetValue(q[2],j);
    if q[3]='+'then
      Inc(j)
    else
      if j=0then
        i:=q[5]
      else
        Dec(j);
    u.AddOrSetValue(q[2],j)
  until i[1]='"';
  WriteLn(i);
  for v in u do
    Write(v.Key,'=',v.Value,' ')
end.

1

PHP, 446 441 402 398 395 389 371 370 366 अक्षर

<?$t=trim;$e=explode;while($l=$t(fgets(STDIN))){if(strpos($l,"=")){foreach($e(" ",$l)as$b){list($k,$c)=$e("=",$b);$v[$k]=$c;}break;}list($k,$d)=$e(":",$l);$r[$z=$t($k)]=$t($d);$c=$c?:$z;}while($d=$e(" ",$r[$c],4)){$c=$v[$a=$d[0]]||!$d[3]?$d[2]:$d[3];if(!$r[$c]){eval("echo $c.'\n';");foreach($v as$k=>$c)echo$k."=".$c." ";die;}if(!$d[3]&&++$v[$a]||$v[$a]&&--$v[$a]);}

Ungolfed


<?php

$register = array();
$values = array();

while($line = trim(fgets(STDIN))){

    if(strpos($line, "=")){

        // Set each value and then continue to the calculations

        foreach(explode(" ", $line) as $var){
            list($key, $val) = explode("=", $var);

            $values[$key] = $val;
        }

        break;
    }

    list($key, $data) = explode(":", $line);

    // Add data to the register

    $register[$z = trim($key)] = trim($data);

    // Set the first register

    $current = $current?:$z;
}

while($data = explode(" ", $register[$current], 4)){

    // Determine next register and current register

    $current = $values[$target = $data[0]] || !$data[3]? $data[2] : $data[3];

    // Will return true if the register does not exist (Messages wont have a register)

    if(!$register[$current]){

        // No need to strip the quotes this way

        eval("echo$current.'\n';");

        // Print all values in the right formatting

        foreach($values as $key => $val)
            echo $key."=".$val." ";

        die();
    }

    // Only subtraction has a third index
    // Only positive values return true

    // If there is no third index, then increase the value
    // If there is a third index, increment the decrease the value if it is positive

    // Uses PHP's short-circuit operators

    if(!$data[3] && ++$values[$target] || $values[$target] && --$values[$target]);
}

बदलाव का


446 -> 441 : पहले राज्य के लिए तार का समर्थन करता है, और कुछ मामूली संपीड़न
441 -> 402 : संपीड़ित यदि / और असाइनमेंट स्टेटमेंट जितना संभव हो
402 -> 398 : फ़ंक्शन नामों को स्थिरांक के रूप में उपयोग किया जा सकता है जिसे स्ट्रिंग्स के रूप में उपयोग किया जा सकता है।
398 -> 395 : शॉर्ट सर्किट ऑपरेटरों का उपयोग करता है
395 -> 389 : किसी अन्य भाग की आवश्यकता नहीं है
389 -> 371 : सरणी_की_टेक्स्ट का उपयोग करने की आवश्यकता नहीं है ()
371 -> 370 : हटाए गए अनावश्यक स्थान
370>> 366 : में दो अनावश्यक स्थानों को हटा दिया गया। सबसे आगे


1

ग्रूवी, 338

m={s=r=[:];z=[:]
it.eachLine{e->((e==~/\w+=.*/)?{(e=~/((\w+)=(\d+))+/).each{r[it[2]]=it[3] as int}}:{f=(e=~/(\w+) : (.*)/)[0];s=s?:f[1];z[f[1]]=f[2];})()}
while(s[0]!='"'){p=(z[s]=~/(\w+) (.) (\w+|(?:".*?")) ?(.*)?/)[0];s=p[3];a=r[p[1]]?:0;r[p[1]]=p[2]=='-'?a?a-1:{s=p[4];0}():a+1}
println s[1..-2]+"\n"+r.collect{k,v->"$k=$v"}.join(' ')}


['''s0 : a - s1 "Ok"
s1 : b + s0
a=3 b=4''':'''Ok
a=0 b=7''',
'''init : t - init d0
d0 : a - d1 a0
d1 : b + d2
d2 : t + d0
a0 : t - a1 "Ok"
a1 : a + a0
a=3 b=4''':'''Ok
a=3 b=7 t=0''',
'''s0 : t - s0 s1
s1 : t + "t is 1"
t=17''':'''t is 1
t=1''',
'''s0 : t - "t is nonzero" "t is zero"
t=1''':'''t is nonzero
t=0''',
'''init0 : k - init1 init3
init1 : r + init2
init2 : t + init0
init3 : t - init4 init5
init4 : k + init3
init5 : r - init6 "ERROR k is 0"
init6 : i + init7
init7 : n - loop0 "ERROR n is 0"
loop0 : n - loop1 "Ok"
loop1 : i + loop2
loop2 : k - loop3 loop5
loop3 : r + loop4
loop4 : t + loop2
loop5 : t - loop6 loop7
loop6 : k + loop5
loop7 : i - loop8 loopa
loop8 : r - loop9 loopc
loop9 : t + loop7
loopa : t - loopb loop7
loopb : i + loopa
loopc : t - loopd loopf
loopd : i + loope
loope : r + loopc
loopf : i + loop0
n=40 k=3''':'''Ok
i=40 k=3 n=0 r=27 t=0'''].collect {input,expectedOutput->
    def actualOutput = m(input)
    actualOutput == expectedOutput
}

1
मैं यह परीक्षण किया है, लेकिन यह stdout करने के लिए कुछ भी उत्पादन करने के लिए प्रतीत नहीं होता है । परिणाम देखने के लिए मुझे क्या जोड़ने की आवश्यकता है? (पीएस कल्पना कहती है कि आउटपुट में रजिस्टरों का क्रम अप्रासंगिक है, इसलिए आप 7 वर्णों को बचा सकते हैं .sort())
पीटर टेलर

@ टिप के लिए धन्यवाद - मुझे printlnअच्छी तरह से - के लिए 8 वर्ण जोड़ने होंगे !
आर्मंड

1

क्लोजर (344 वर्ण)

"पठनीयता" के लिए कुछ लाइनब्रेक के साथ:

(let[i(apply str(butlast(slurp *in*)))]
(loop[s(read-string i)p(->> i(replace(zipmap":\n=""[] "))(apply str)(format"{%s}")read-string)]
(let[c(p s)](cond(string? s)(println s"\n"(filter #(number?(% 1))p))
(=(c 1)'-)(let[z(=(get p(c 0)0)0)](recur(c(if z 3 2))(if z p(update-in p[(c 0)]dec))))
1(recur(c 2)(update-in p[(c 0)]#(if %(inc %)1)))))))

1

परिशिष्ट भाग () () (852) (718)

वास्तविक समय के लिए इस समय। सभी परीक्षण मामलों को निष्पादित करता है। यह अभी भी आरएम प्रोग्राम को प्रोग्राम स्ट्रीम में तुरंत पालन करने की आवश्यकता है।

संपादित करें: अधिक फैक्टरिंग, कम प्रक्रिया नाम।

errordict/undefined{& " * 34 eq{.()= !{& " .(=). load " .( ).}forall ^()=
stop}{^ ^ " 0 @ : 0}ifelse}put<</^{pop}/&{dup}/:{def}/#{exch}/*{& 0
get}/.{print}/~{1 index}/"{=string cvs}/`{cvn # ^ #}/+={~ load add :}/++{1
~ length 1 sub getinterval}/S{/I where{^}{/I ~ cvx :}ifelse}/D{/? # :/_ #
cvlit :}/+{D S({//_ 1 +=//?})$ ^ :}/-{/| # : D S({//_ load 0 ne{//_ -1
+=//?}{//|}ifelse})$ ^ :}/![]/@{~/! #[# cvn ! aload length & 1 add #
roll]:}/;{(=)search ^ # ^ # cvi @ :}/${* 32 eq{++}if * 34 eq{& ++(")search
^ length 2 add 4 3 roll # 0 # getinterval cvx `}{token ^
#}ifelse}>>begin{currentfile =string readline ^( : )search{`( + )search{`
$ ^ +}{( - )search ^ ` $ $ ^ -}ifelse}{( ){search{;}{; I}ifelse}loop}ifelse}loop

संलग्न कार्यक्रम के साथ इंडेंट किया और टिप्पणी की।

%!
%Minsky Register Machine Simulation
errordict/undefined{ %replace the handler for the /undefined error
    & " * 34 eq{ % if, after conversion to string, it begins with '"',
        .()= !{ % print it, print newline, iterate through the register list
            & " .(=). load " .( ). % print regname=value
        }forall ^()= stop % print newline, END PROGRAM
    }{ % if it doesn't begin with '"', it's an uninitialized register
        ^ ^ " 0 @ : 0 %initialize register to zero, return zero
    }ifelse
}put
<<
/^{pop}
/&{dup}
/:{def} % cf FORTH
/#{exch}
/*{& 0 get} % cf C
/.{print} % cf BF

% these fragments were repeated several times
/~{1 index}
/"{=string cvs} % convert to string
/`{cvn # ^ #} % convert to name, exch, pop, exch
/+={~ load add :} % add a value to a variable
/++{1 ~ length 1 sub getinterval} % increment a "string pointer"

/S{/I where{^}{/I ~ cvx :}ifelse} %setINIT define initial state unless already done
/D{/? # :/_ # cvlit :} %sr define state and register for generated procedure
/+{D S({//_ 1 +=//?})$ ^ :} % generate an increment state and define
/-{/| # : D S({//_ load 0 ne{//_ -1 +=//?}{//|}ifelse})$ ^ :} % decrement state
/![] %REGS list of registers
/@{~/! #[# cvn ! aload length & 1 add # roll]:} %addreg append to REGS
/;{(=)search ^ # ^ # cvi @ :} %regline process a register assignment
/${ %tpe extract the next token or "string"
    * 32 eq{++}if %skip ahead if space
    * 34 eq{ %if quote, find the end-quote and snag both
        & ++(")search ^ length 2 add 4 3 roll # 0 # getinterval cvx `
    }{
        token ^ # %not a quote: pull a token, exch, pop
    }ifelse
}
>>begin

{
    currentfile =string readline ^
    ( : )search{ % if it's a state line
        `( + )search{ % if it's an increment
            ` $ ^ + %parse it
        }{
            ( - )search ^ ` $ $ ^ - %it's a decrement. Parse it
        }ifelse
    }{ % not a state, do register assignments, and call initial state
        ( ){search{;}{; I}ifelse}loop %Look Ma, no `exit`!
    }ifelse
}loop
init0 : k - init1 init3
init1 : r + init2
init2 : t + init0
init3 : t - init4 init5
init4 : k + init3
init5 : r - init6 "ERROR k is 0"
init6 : i + init7
init7 : n - loop0 "ERROR n is 0"
loop0 : n - loop1 "Ok"
loop1 : i + loop2
loop2 : k - loop3 loop5
loop3 : r + loop4
loop4 : t + loop2
loop5 : t - loop6 loop7
loop6 : k + loop5
loop7 : i - loop8 loopa
loop8 : r - loop9 loopc
loop9 : t + loop7
loopa : t - loopb loop7
loopb : i + loopa
loopc : t - loopd loopf
loopd : i + loope
loope : r + loopc
loopf : i + loop0
n=40 k=3

जब से मैंने कोई पोस्टस्क्रिप्ट लिखी है, तब से कुछ समय है, लेकिन क्या आप इस तरह के नामों के साथ फ़ंक्शन को परिभाषित कर रहे हैं regline? क्या आप उन्हें चीजों की तरह बुलाकर बहुत बचत नहीं कर सकते R?
पीटर टेलर

हाँ बिलकुल। लेकिन राज्य के साथ इन सभी परिभाषाओं के साथ और एक ही शब्दकोश में नाम दर्ज करने के बाद से एक संभावित समस्या भी है। इसलिए मैं कुछ mnemonic मूल्य के साथ विराम चिह्न खोजने की कोशिश कर रहा हूं (इसलिए मैं अभी भी इसे पढ़ सकता हूं :)। मैं और अधिक एल्गोरिदम की कटौती की उम्मीद कर रहा हूं, इसलिए मैं बहुत ऊर्जा खर्च नहीं करना चाहता था इससे पहले कि मैं इसे ताजा आंखों से देख सकूं।
लूसर डॉग

1

AWK - 447

BEGIN{FS=":"}NF<2{split($1,x," ");for(y in x){split(x[y],q,"=");
g[q[1]]=int(q[2])}}NF>1{w=$1;l=$2;gsub(/ /,"",w);if(!a)a=w;for(i=0;;)
{sub(/^ +/,"",l);if(l=="")break;if(substr(l,1,1)=="\""){l=substr(l,2);
z=index(l,"\"")}else{z=index(l," ");z||z=length(l)+1}d[w,i++]=
substr(l,1,z-1);l=substr(l,z+1)}}END{for(;;){if(!((a,0)in d))break;h=d[a,0];
if(d[a,1]~/+/){g[h]++;a=d[a,2]}else{a=g[h]?d[a,2]:d[a,3];g[h]&&g[h]--}}
print a;for(r in g)print r"="g[r]}

यह पहले परीक्षण के लिए आउटपुट है:

% cat | awk -f mrm1.awk
s0 : a - s1 "Ok"
s1 : b + s0
a=3 b=4
^D
Ok
a=0
b=7

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