Minsky 등록기 시뮬레이션 (I)


26

많은 형식주의가 있기 때문에 다른 출처가 유용하다는 것을 알 수 있지만 필요하지 않을 정도로 명확하게 지정하고 싶습니다.

RM은 유한 상태 머신과 유한 한 수의 명명 된 레지스터로 구성되며, 각각 음수가 아닌 정수를 보유합니다. 텍스트를 쉽게 입력 할 수 있도록이 작업에서는 상태 이름도 지정해야합니다.

상태에는 세 가지 유형이 있습니다. 증가와 감소는 둘 다 특정 레지스터를 참조합니다. 종료합니다. 증가 상태는 레지스터를 증가시키고 제어를 해당 후속 작업으로 전달합니다. 감소 상태에는 두 개의 후속 작업이 있습니다. 레지스터가 0이 아닌 경우 감소하고 첫 번째 후속 작업에 제어를 전달합니다. 그렇지 않으면 (즉, 레지스터가 0 임) 단순히 두 번째 후속 작업에 제어를 전달합니다.

프로그래밍 언어 인 "niceness"의 경우 종료 상태는 인쇄하기 위해 하드 코드 된 문자열을 사용하므로 예외적으로 종료 될 수 있습니다.

입력은 표준 입력입니다. 입력 형식은 상태 당 한 줄로 구성되며 초기 레지스터 내용이 이어집니다. 첫 번째 줄은 초기 상태입니다. 상태 라인의 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

식별자와 메시지의 정의에는 약간의 융통성이 있습니다. 프로그램 비어 있지 않은 영숫자 문자열을 식별자로 받아 들여야 하지만 원하는 경우보다 일반적인 문자열을 받아 들일 수 있습니다 (예 : 언어에서 밑줄이있는 식별자를 지원하고 작업하기가 더 쉬운 경우). 마찬가지로, 메시지를 당신이 해야한다 영숫자와 공간의 비어 있지 않은 문자열을 받아,하지만 당신은 할 수 있습니다 당신이 원하는 경우에 탈출 줄 바꿈 및 따옴표 문자를 수있는 더 복잡한 문자열을 받아들입니다.

초기 레지스터 값을 제공하는 마지막 입력 행은 공백으로 구분 된 identifier = int 할당 목록이며 비어 있지 않아야합니다. 프로그램에 명명 된 모든 레지스터를 초기화 할 필요는 없습니다. 초기화되지 않은 것은 0으로 간주됩니다.

프로그램은 입력을 읽고 RM을 시뮬레이션해야합니다. 종료 상태에 도달하면 메시지, 줄 바꿈 및 모든 레지스터의 값 (편리하고 사람이 읽을 수있는 형식 및 순서대로)을 표시해야합니다.

참고 : 공식적으로 레지스터에는 제한없는 정수가 있어야합니다. 그러나 레지스터 값이 2 ^ 30을 초과하지 않는다고 가정 할 수 있습니다.

몇 가지 간단한 예

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

예상 결과 :

Ok
a=0 b=7
b + = a, t = 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의 Josephus 문제 코드 문제에서 발췌. 입력은 n (병사 수) 및 k (사전)이며 r의 출력은 생존 한 사람의 위치 (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

시각적으로 생각하고 구문을 이해하는 것이 도움이되는 사람들을위한 그림으로서의 그 프로그램 : 요세푸스 문제 RM

이 골프를 즐겼다면 속편을보십시오 .


입력은 stdin, 파일 또는 다른 장소에서 나옵니까?
Kevin Brown

stdin에서 @Bass.
피터 테일러

1) 공백이있는 메시지, 2) 등호가있는 메시지, 3) inc_line에있는 메시지, 4) dec_line의 첫 번째 상태에있는 메시지, 5) 공백에있는 메시지 사례 3 & 4
MtnViewMark

문법에 오류가 있습니다. dec_line의 두 state_name 항목 사이에 리터럴 공백이 있어야합니다. 사람들이 입력에서 토큰 사이에 여러 공백을 허용하도록 요구하는지 여부도 확실하지 않습니다.
MtnViewMark

2
@Peter : 사양과 균형이 잘 잡힌 코드 고기를 +1하십시오! 여기서 대부분의 질문은 너무 얇습니다.
MtnViewMark

답변:


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.

완전히 다른 방식으로 시작되었지만 많은 부분에서 Ruby 솔루션과 수렴 될까봐 두렵습니다. 루비의 장점은 "no sigils"이고 Perl의 "더 나은 정규식 통합"입니다.

Perl을 읽지 않으면 내부에서 약간의 세부 사항을 확인하십시오.

  • @p=<>: 전체 기계 설명을 읽어 @p
  • /=/,$_{$`}=$' for split$",pop@p: 마지막 기계 설명 줄 ( )의 각 ( for) 할당 ( split$")에 대해 @p등호 ( )를 찾은 /=/다음 값 $'을 hask %_키에 할당$`
  • $o='\w+': 초기 상태는 Perl 정규식 "단어 문자"와 일치하는 첫 번째 상태입니다.
  • 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

@Lowjacker 올바른 레이블에 있는지 확인하는 데 필요하지는 않지만 $'. 정규 표현식의 한 문자이며 $c,외부에서 설명하는 것은 3 입니다. 또는 일부 더 큰 토큰 화 정규식으로 변경됩니다.
JB

10

Python + C, 466 자

RM 프로그램을 C로 컴파일 한 다음 C를 컴파일하고 실행하는 파이썬 프로그램은 재미있게 사용할 수 있습니다.

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
@ Nabb : 버즈 킬. 올바른 위치에 밑줄 접두사를 추가하기 위해 독자에게 맡깁니다.
Keith Randall

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가 필요합니다.


  • 편집 : (498-> 482) 다양한 작은 인라인 및 @FUZxxl의 제안 중 일부
  • 편집 : (482-> 453) 레지스터의 실제 숫자를 사용하여 다시 전환하십시오. 많은 골프 트릭 적용
  • 편집 : (453-> 444) 인라인 출력 형식 및 초기 값 구문 분석

Haskell을 모르기 때문에 모든 구문을 해독 할 수는 없지만 레지스터 내용에 대해 목록을 사용하고 있음을 확인할 수있을만큼 해독 할 수 있습니다. ints를 사용하는 것보다 짧다는 것에 놀랐습니다.
피터 테일러

where세미콜론으로 구분 된 단일 행에 로컬 바인딩을 넣으면 6자를 절약 할 수 있습니다. 그리고 q자세한 if-then-else를 패턴 가드로 변경하여 정의에 일부 문자를 저장할 수 있다고 생각합니다 .
FUZxxl

또한 세 번째 값이 밑줄 "-"의 정의에 q있고 대신 밑줄을 사용 한다고 맹목적으로 가정하십시오 .
FUZxxl

8 줄을로 변경하여 다른 문자를 저장할 수 있다고 생각합니다 q[_,_,r,_,s,z]d|maybe t(==0)$lookup r d=n z d|t=n s$r%(-1)$d. 그러나 어쨌든이 프로그램은 매우 훌륭합니다.
FUZxxl

lexPrelude 를 활용하면 구문 분석 코드를 상당히 단축 할 수 있습니다 . 예를 들어 f[]=[];f s=lex s>>= \(t,r)->t:f r인용 된 문자열을 올바르게 처리하면서 줄을 토큰으로 나눕니다.
hammar

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} /}

레이블 접두사에서 서로 실패 할 것으로 예상됩니다. 생각?
JB

예제 이외의 다른 경우에는 작동하지 않는 것 같습니다. 이게 뭐가 문제 야 ?
JB

나는 그것이 지금 고쳐 졌다고 생각한다.
Lowjacker

아 훨씬 좋아 고맙습니다.
JB

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]);}

언 골프


<?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 : else 부분이 필요 없음 389-
> 371 : array_key_exists ()를 사용할 필요가 없습니다. 371-
> 370 : 불필요한 공간 제거 370-
> 366 : 불필요한 두 공간 제거 foreach


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에 아무것도 출력하지 않는 것 같습니다 . 결과를 보려면 무엇을 추가해야합니까? (PS 사양에 따르면 출력의 레지스터 순서는 관련이 없으므로에서 7자를 저장할 수 있습니다. .sort())
Peter Taylor

@Peter 팁 주셔서 감사합니다-나는 8 문자를 추가해야합니다 println-아 잘!
Armand

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)

이번에는 진짜로. 모든 테스트 사례를 실행합니다. 여전히 프로그램 스트림에서 RM 프로그램을 즉시 따라야합니다.

편집 : 더 팩토링하고 절차 이름을 줄였습니다.

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

PostScript를 작성한 지 오래되었지만 이름이 같은 함수를 정의하고 regline있습니까? 당신은 그들과 같은 것을 부름으로써 많은 것을 구할 수 없습니까 R?
피터 테일러

물론 이죠 그러나 이러한 모든 정의가 동일한 사전에 상태 및 레지스터 이름과 공존하기 때문에 잠재적 인 문제가 있습니다. 내가와 구두점 문자 찾기 위해 노력했습니다 그래서 일부 니모닉 값을 (나는 아직도 그것을 읽을 수 있도록 :). 또한 알고리즘 감소를 더 많이 찾고 싶어서 신선한 눈으로 볼 수 있기 전에 너무 많은 에너지를 소비하고 싶지 않았습니다.
luser droog

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

1

STAX , 115 100 바이트

╥áípßNtP~£G±☼ΩtHô⌐╒╡~·7╝su9êq7h50Z`╩ë&ñ╝←j╞.½5└∩√I|ù┤╧Åτ╘8┼ç╕╒Æ►^█₧♫÷?²H½$IG☺S╚]«♀_≥å∩A+∩╣Δ└▐♫!}♥swα

실행 및 디버깅

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.