Ada banyak formalisme, jadi sementara Anda mungkin menemukan sumber-sumber lain yang berguna, saya berharap untuk menentukan ini dengan cukup jelas sehingga tidak perlu.
RM terdiri dari mesin keadaan terbatas dan sejumlah register bernama, yang masing-masing memegang bilangan bulat non-negatif. Untuk memudahkan input teks, tugas ini mengharuskan status yang disebutkan juga.
Ada tiga jenis negara: kenaikan dan penurunan, yang keduanya merujuk pada register tertentu; dan mengakhiri. Status kenaikan menambah registernya dan memberikan kendali kepada satu penggantinya. Negara penurunan memiliki dua penerus: jika registernya bukan nol maka ia menurunkannya dan memberikan kendali kepada penerus pertama; jika tidak (mis. register adalah nol) itu hanya melewati kontrol ke penerus kedua.
Untuk "kebaikan" sebagai bahasa pemrograman, status terminate mengambil string hard-coded untuk dicetak (sehingga Anda dapat mengindikasikan terminasi yang luar biasa).
Masukan dari stdin. Format input terdiri dari satu baris per negara, diikuti oleh konten register awal. Baris pertama adalah kondisi awal. BNF untuk jalur negara adalah:
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
Ada beberapa fleksibilitas dalam definisi pengidentifikasi dan pesan. Program Anda harus menerima string alfanumerik yang tidak kosong sebagai pengidentifikasi, tetapi mungkin menerima string yang lebih umum jika Anda lebih suka (misalnya jika bahasa Anda mendukung pengidentifikasi dengan garis bawah dan itu lebih mudah bagi Anda untuk bekerja dengannya). Demikian pula, untuk pesan Anda harus menerima string alfanumerik dan spasi yang tidak kosong, tetapi Anda dapat menerima string yang lebih kompleks yang memungkinkan baris baru dan karakter kutip ganda lolos jika Anda mau.
Baris input terakhir, yang memberikan nilai register awal, adalah daftar pengidentifikasi = int penugasan yang dipisahkan spasi, yang harus non-kosong. Tidak perlu menginisialisasi semua register yang disebutkan dalam program: semua yang tidak diinisialisasi diasumsikan 0.
Program Anda harus membaca input dan mensimulasikan RM. Ketika mencapai kondisi terminasi, ia harus memancarkan pesan, baris baru, dan kemudian nilai-nilai semua register (dalam format apa pun yang mudah dibaca oleh manusia, dalam format apa pun).
Catatan: secara formal register harus memegang bilangan bulat tidak terikat. Namun, Anda dapat jika Anda berasumsi bahwa nilai register tidak akan melebihi 2 ^ 30.
Beberapa contoh sederhana
a + = b, a = 0s0 : a - s1 "Ok"
s1 : b + s0
a=3 b=4
Hasil yang diharapkan:
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
Hasil yang diharapkan:
Ok
a=3 b=7 t=0
Uji kasus untuk mesin rumit untuk parse
s0 : t - s0 s1
s1 : t + "t is 1"
t=17
Hasil yang diharapkan:
t is 1
t=1
dan
s0 : t - "t is nonzero" "t is zero"
t=1
Hasil yang diharapkan:
t is nonzero
t=0
Contoh yang lebih rumit
Diambil dari tantangan kode masalah DailyWTF Josephus. Input adalah n (jumlah tentara) dan k (muka) dan output dalam r adalah posisi (diindeks nol) dari orang yang selamat.
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
Hasil yang diharapkan:
Ok
i=40 k=3 n=0 r=27 t=0
Program itu sebagai gambar, bagi mereka yang berpikir secara visual dan akan sangat membantu untuk memahami sintaksis:
Jika Anda menikmati golf ini, lihat sekuelnya .
sumber
Jawaban:
Perl, 166
Jalankan dengan
perl -M5.010 file
.Itu mulai sangat berbeda, tapi saya khawatir itu menyatu dengan solusi Ruby di banyak daerah menjelang akhir. Sepertinya keuntungan Ruby adalah "no sigils", dan Perl "integrasi regex yang lebih baik".
Sedikit detail dari jeroan, jika Anda tidak membaca Perl:
@p=<>
: baca seluruh deskripsi mesin ke@p
/=/,$_{$`}=$' for split$",pop@p
: untuk setiapfor
penugasan (split$"
) pada baris deskripsi mesin terakhir (@p
), cari tanda sama dengan (/=/
) lalu tetapkan nilai$'
ke%_
kunci hask$`
$o='\w+'
: keadaan awal akan menjadi yang pertama untuk mencocokkan Perl regex "karakter kata"until/"/
: loop sampai kami mencapai status terminasi:map{($r,$o,$,,$b)=$'=~/".*?"|\S+/g if/^$o :/}@p
: loop pada deskripsi mesin@p
: ketika kita berada di baris yang sesuai dengan keadaan saat ini (if/^$o :/
), tokenize (/".*?"|\S+/g
) sisa baris$'
ke variabel($r,$o,$,,$b)
. Trik: variabel yang sama$o
jika awalnya digunakan untuk nama label dan selanjutnya untuk operator. Segera setelah label cocok, operator menimpanya, dan karena label tidak dapat (secara wajar) dinamai + atau -, label tidak akan cocok lagi.$_=$o=($_{$r}+=','cmp$o)<0?do{$_{$r}=0;$b}:$,
:- sesuaikan register target
$_{$r}
naik atau turun (ASCII magic:','cmp'+'
adalah 1 sedangkan','cmp'-'
-1);- jika hasilnya negatif (
<0?
, hanya bisa terjadi untuk -)- maka tetap pada 0 (
$_{$r}=0
) dan kembalikan label kedua$b
;- lain kembalikan label pertama (mungkin satu-satunya)
$,
$,
bukan$a
jadi itu bisa menempel token berikutnyauntil
tanpa spasi putih di antaranya.say for eval,%_
: dump report (eval
) dan isi register di%_
sumber
/^$o :/
. Tanda sisipan saja sudah cukup untuk memastikan Anda hanya melihat label.$'
. Itu satu karakter di regex, itu akan menjadi tiga$c,
untuk menjelaskan dari luar. Secara bergantian beberapa yang lebih besar namun berubah menjadi regen tokenizing.Python + C, 466 karakter
Hanya untuk bersenang-senang, program python yang mengkompilasi program RM ke C, lalu mengkompilasi & menjalankan C.
sumber
main
', 'if
', dll.Haskell, 444 karakter
Astaga, itu sulit! Penanganan pesan yang benar dengan spasi di dalamnya membutuhkan biaya lebih dari 70 karakter. Format pemformatan menjadi lebih "terbaca oleh manusia", dan sesuai dengan contoh, biayanya 25 lainnya.
sumber
where
menjadi satu baris yang dipisahkan oleh titik koma dapat menghemat 6 karakter. Dan saya kira Anda bisa menyimpan beberapa karakter dalam definisiq
dengan mengubah verbose jika-maka-lagi menjadi penjaga pola."-"
dalam definisiq
dan gunakan garis bawah sebagai gantinya.q[_,_,r,_,s,z]d|maybe t(==0)$lookup r d=n z d|t=n s$r%(-1)$d
. Tapi bagaimanapun, program ini golf sangat bagus.lex
Prelude. Misalnya sesuatu sepertif[]=[];f s=lex s>>= \(t,r)->t:f r
akan membagi garis menjadi token sambil menangani string yang dikutip dengan benar.Ruby 1.9,
214212211198195192181175173175sumber
Delphi, 646
Delphi tidak menawarkan banyak hal berkaitan dengan string dan hal-hal yang membelah. Untungnya, kami memiliki koleksi generik, yang memang sedikit membantu, tetapi ini masih merupakan solusi yang agak besar:
Di sini versi indentasi dan komentar:
sumber
PHP,
446441402398395389371370366 karakterTidak disatukan
Changelog
446 -> 441 : Mendukung string untuk status pertama, dan sedikit kompresi
441 -> 402 : Terkompresi jika / lain dan pernyataan penugasan sebanyak mungkin
402 -> 398 : Nama fungsi dapat digunakan sebagai konstanta yang dapat digunakan sebagai string
398 -> 395 : Menggunakan operator hubung singkat
395 -> 389 : Tidak perlu untuk bagian lain
389 -> 371 : Tidak perlu menggunakan array_key_exists ()
371 -> 370 : Menghapus ruang yang tidak dibutuhkan
370 -> 366 : Menghapus dua ruang yang tidak dibutuhkan di pendahuluan
sumber
Groovy, 338
sumber
.sort()
)println
- ah well!Clojure (344 karakter)
Dengan beberapa linebreak untuk "keterbacaan":
sumber
Postscript () ()
(852)(718)Untuk real kali ini. Menjalankan semua test case. Masih membutuhkan program RM untuk segera mengikuti aliran program.
Sunting: Lebih banyak anjak piutang, nama prosedur yang dikurangi.
Diindentasi dan dikomentari dengan program terlampir.
sumber
regline
? Tidak bisakah Anda menghemat banyak dengan menyebut mereka hal-hal sepertiR
?AWK - 447
Ini adalah output untuk tes pertama:
sumber
Stax ,
115100 byteJalankan dan debug itu
sumber