Minsky Kayıt Makinesinin Simülasyonu (II)


11

Bu bir Simüle Kayıt Minsky Kayıt Makinesi (I) ' nin bir uzantısıdır . Buradaki tüm açıklamaları tekrarlamayacağım, lütfen önce bu sorun açıklamasını okuyun.

Kısım (I) 'deki dilbilgisi mümkün olduğunca basitti, ancak oldukça uzun programlarla sonuçlanıyor. Bu bir kod golf sitesi olduğundan, bir golf grameri isterdim, değil mi?

Yüksek düzeyde, orijinal dilbilgisinden değişiklikler aşağıdaki gibidir:

  • İlk satırdaki etiket isteğe bağlıdır
  • İki bitişik tanımlayıcıyı ayırmak için gereken yerler dışında boşluk isteğe bağlıdır
  • Devletler satır içi olabilir. Belirsiz ayrıştırma sağlamak için, bir azaltma işleminin ilk durumu satır içi durumsa, parantez içine alınmalıdır. Bu, herhangi bir programın tek bir astarda golf oynayabileceği anlamına gelir.

Örneğin, orijinal test vakalarında:

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

Golfçü dilbilgisinde bu kısaltılabilir:

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

ya da:

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

"Program" satırları için yeni BNF (veri olan son satırın aksine):

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

Tanımlayıcılar ve mesajlar önceki zorluktaki gibi esnektir.


Önceki zorluktaki tüm test senaryoları hala geçerlidir. Ayrıca, aşağıdaki golf edilmiş Josephus çözümü dilbilgisinin çoğunu kullanmalıdır:

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

Beklenen çıktı:

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

Ve bence bu kalan davayı kapsıyor:

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

Beklenen çıktı:

nop
k=3

Tüm programların mantıklı semantiğe sahip olacağını varsayabilirsiniz. Özellikle, en az bir durumları olacak ve bir durumu yeniden tanımlamayacaklar. Ancak, daha önce olduğu gibi, bir durum tanımlanmadan önce kullanılabilir.

Puanlama, kod golfünün bir çeşididir. Bağımsız bir program yazabilirsiniz ve UTF-8 kodlamasından sonra bayt cinsinden program uzunluğu olarak puanlanır. Alternatif olarak, kodun yeniden kullanılması İyi Bir Şey olduğu için, (I) parçasını n1baytlara uyguladıysanız , bir parça (II) programını, orijinaline borulamaya hazır bir parça (I) programına dönüştüren bir program yazabilirsiniz. Daha sonra puanınız, dönüşüm programınızın uzunluğu artı olacaktır ceil(n1 / 2).

Not Dönüştürmeyi seçerseniz, adsız durumlar için adlandırılmış durumlarla çakışmayacaklarını garanti edecek şekilde adlar oluşturmanız gerekir.

Yanıtlar:


6

Haskell, 552 499 493 karakter

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

Az çok tam bir yeniden yazma işlemi yaptı. CPS yerine, henüz ayrıştırılmadığı durumları (tembellik için yay!) Ve diğer bazı ince ayarları yapmak için kendi çıktısını okuyan bir RWS monad ile değiştirildi.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.