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


11

これはSimsky a Minsky Register Machine(I)の拡張です。私はそこですべての説明を繰り返すつもりはないので、まずその問題の説明を読んでください。

部分(I)の文法は可能な限り単純でしたが、かなり長いプログラムになります。これはコードゴルフサイトであるため、ゴルフの文法が必要です。

高レベルでは、元の文法からの変更は次のとおりです。

  • 最初の行のラベルはオプションです
  • 2つの隣接する識別子を分離する必要がある場合を除き、空白はオプションです
  • 状態はインライン化できます。曖昧さのない構文解析を保証するために、デクリメント操作の最初の状態がインライン状態の場合、括弧で囲む必要があります。これは、どのプログラムでもワンライナーにゴルフできることを意味します。

たとえば、元のテストケースでは次のとおりでした。

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

ゴルフの文法では、これは次のように短縮できます。

init:t-init d
d:a-(b+t+d)a
a:t-(a+a)"Ok"
a=3 b=4

あるいは:

init:t-init d:a-(b+t+d)a:t-(a+a)"Ok"
a=3 b=4

「プログラム」行の新しいBNF(最終行とは対照的)は次のとおりです。

program    ::= first_line (newline line)*
first_line ::= cmd
line       ::= named_cmd
state      ::= state_name
             | cmd
             | '"' message '"'
delim_state::= '(' cmd ')'
             | '"' message '"'
cmd        ::= raw_cmd
             | named_cmd
named_cmd  ::= state_name ' '* ':' ' '* raw_cmd
raw_cmd    ::= inc_cmd
             | dec_cmd
inc_cmd    ::= reg_name ' '* '+' ' '* state
dec_cmd    ::= reg_name ' '* '-' ' '* delim_state ' '* state
             | reg_name ' '* '-' ' '* state_name ' '* delim_state
             | reg_name ' '* '-' ' '* state_name ' '+ state
state_name ::= identifier
reg_name   ::= identifier

前の課題と同様に、識別子とメッセージは柔軟です。


前のチャレンジのテストケースはすべて引き続き適用可能です。さらに、次のゴルフジョセフスソリューションは、ほとんどの文法を実行する必要があります。

in:k-(r+t+in)in2:t-(k+in2)r-(i+n-0"ERROR n is 0")"ERROR k is 0"
0:n-(i+2:k-(r+t+2)5:t-(k+5)7:i-(r-(t+7)c:t-(i+r+c)i+0)a:t-(i+a)7)"Ok"
n=40 k=3

期待される出力:

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

そして、これは残りのケースをカバーすると思います:

k+k-"nop""assert false"
k=3

期待される出力:

nop
k=3

すべてのプログラムが意味のあるセマンティクスを持っていると仮定することができます。特に、それらは少なくとも1つの状態を持ち、状態を再定義しません。ただし、以前と同様に、状態は定義される前に使用される場合があります。

スコアリングはコードゴルフの変形です。自己完結型のプログラムを書くことができ、UTF-8エンコード後にプログラムの長さをバイト単位でスコア付けします。あるいは、コードの再利用は良いことなので、パート(I)をn1バイト単位で実装している場合、パート(II)プログラムをパート(I)プログラムに変換して、オリジナルにパイプできるようにするプログラムを作成できます。スコアは、変換プログラムの長さにを加えたものになりceil(n1 / 2)ます。

注意:変換を選択する場合、名前付き状態と衝突しないことを保証するような方法で、匿名状態の名前を生成する必要があります。

回答:


6

Haskell、552 499 493文字

import Control.Monad.RWS
import Data.Map
main=interact$z.lines
z x=let(s:_,w)=evalRWS(mapM(q.t)x)w[]in s.f.i.t$last x 
p=get>>=q
q(l:":":x)=x%do a<-p;tell$f[(l,a)];r a
q(v:"+":x)=x%fmap(.a v 1)p
q(v:"-":x)=x%liftM2(d v)p p
q(('"':s):x)=x%r(\w->unlines[init s,do(v,x)<-assocs w;v++'=':show x++" "])
q(n:x)|n<"*"=x%p|1<3=x%asks(!n)
d v p n w|member v w&&w!v>0=p$a v(-1)w|1<3=n w
t[]=[];t x=lex x>>= \(y,x)->y:t x
i(v:_:x:t)=(v,read x):i t;i[]=[]
x%m=put x>>m;r=return;a=insertWith(+);f=fromList

多かれ少なかれ完全に書き直しました。CPSをRWSモナドに置き換え、独自の出力を読み取って、まだ解析されていない状態を検索します(怠なのはいや!)、およびその他の調整。

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