ミンスキーレジスターマシンのシミュレーション(I)


26

多くの形式がありますので、他の情報源が役立つと思うかもしれませんが、それらが必要でないように十分明確に指定したいと思います。

RMは、有限状態マシンと有限数の名前付きレジスタで構成され、各レジスタには非負の整数が保持されます。テキスト入力を簡単にするために、このタスクでは状態にも名前を付ける必要があります。

状態には3つのタイプがあります。増分と減分です。どちらも特定のレジスタを参照します。そして終了します。インクリメント状態はレジスタをインクリメントし、制御を1つの後続に渡します。デクリメント状態には2つの後続操作があります。レジスタがゼロ以外の場合、デクリメントして最初の後続操作に制御を渡します。それ以外の場合(つまり、レジスターがゼロ)、制御を2番目の後続に単純に渡します。

プログラミング言語としての「ナイスネス」の場合、終了状態はハードコードされた文字列を使用して印刷します(したがって、例外終了を示すことができます)。

入力は標準入力からです。入力形式は、状態ごとに1行で構成され、その後に初期レジスタの内容が続きます。最初の行は初期状態です。状態ラインの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の出力は生き残った人の(ゼロから始まる)位置です。

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

このゴルフを楽しんだ場合は、続編をご覧ください


入力は標準入力、ファイル、または他の場所から行われますか?
ケビンブラウン

@ Bass、stdinから。
ピーターテイラー

1)スペースのあるメッセージ、2)等号のメッセージ、3)inc_lineのメッセージ、4)dec_lineの最初の状態のメッセージ、5)スペースのメッセージケース3および
4。– MtnViewMark

文法にエラーがあります。dec_lineの2つのstate_nameエントリの間にリテラルスペースが必要です。また、入力でトークン間の複数のスペースを受け入れるように人々に要求するつもりであるかどうかも不明です。
MtnViewMark

2
@Peter:仕様と操作の余地のバランスがとれた、本当に肉付きの良いコードゴルフのために+1!ここでの質問のほとんどは非常に薄すぎま​​した。
MtnViewMark

回答:


10

Perl、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ソリューションに収束したのではないかと思います。Rubyの利点は「シギルなし」であり、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、行$'を変数にtokenize()します($r,$o,$,,$b)。トリック:$o最初にラベル名に使用され、その後オペレーターに使用される場合、同じ変数。ラベルが一致するとすぐに、オペレーターがそれをオーバーライドし、ラベルに(合理的に)名前を付けることができないため(+または-)、再び一致することはありません。
    • $_=$o=($_{$r}+=','cmp$o)<0?do{$_{$r}=0;$b}:$,
      -ターゲットレジスタを$_{$r}上下に調整します(ASCIIマジック:','cmp'+'1に対して','cmp'-'-1)。
      -結果が負の場合(<0?、-のみ発生する可能性があります)
      -0($_{$r}=0)のままで、2番目のラベルを返し$bます。
      -それ以外の場合、最初の(おそらく唯一の)ラベルを返す$,
    • ところで、$,代わりに、空白を入れず$aに次のトークンに接着することができますuntil
  • say for eval,%_:レポートのダンプ(eval)およびレジスタの内容%_

あなたは本当にコロンを必要としません/^$o :/。キャレットだけで、ラベルのみを表示できます。
ロージャッカー

@Lowjacker正しいラベルにいると判断するのにそれは必要ありませんが、に入れないようにする必要があり$'ます。正規表現では1文字で、$c,外部から考慮すると3文字になります。代わりに、トークン化正規表現にいくつかの大きなまだ変更。
JB

10

Python + C、466文字

RMプログラムをCにコンパイルし、Cをコンパイルして実行するPythonプログラムです。

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:バズキル。正しい場所に下線プレフィックスを追加するのは読者にお任せします。
キースランドール

6

Haskell、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を知らないので、すべての構文を解読することはできませんが、レジスターの内容にリストを使用していることがわかるほど十分に解読できます。intを使用するよりも短いことに驚きました。
ピーターテイラー

ローカルバインディングをwhereセミコロンで区切られた1行に入れると、6文字節約できます。そしてq、詳細なif-then-elseをパターンガードに変更することで、定義にいくつかの文字を保存できると思います。
-FUZxxl

また、3番目の値が"-"定義に含まれていることをやみくもに想定し、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引用符で囲まれた文字列を正しく処理しながら、行をトークンに分割します。
ハマー

6

Ruby 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

今修正されたと思います。
ロージャッカー

ああ、はるかに良い。ありがとうございました。
JB

3

Delphi、646

Delphiは、文字列などの分割に関してあまり提供していません。幸いなことに、ジェネリックコレクションがありますが、これは少し役立ちますが、これはまだかなり大きなソリューションです:

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:if / elseおよび代入ステートメントを可能な限り圧縮402-
> 398:関数名は、文字列として使用できる定数として使用できます
398-> 395:短絡演算子を使用395-
> 389:else部分は不要389-
> 371:array_key_exists()を使用する必要はない371-
> 370:不要なスペースを削除370-
> 366:不要な2つのスペースを削除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、ヒントをありがとう-8文字追加する必要がありますprintln-ああ!
アルマン

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はドローグ

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

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.