Prelude Syntax-Checker

10

Prelude adalah bahasa pemrograman esoterik, yang memiliki sangat sedikit, tetapi tidak biasa, pembatasan pada apa yang merupakan program yang valid. Setiap blok teks ASCII yang dapat dicetak ("blok" yang berarti bahwa garis ASCII yang dapat dicetak dipisahkan oleh baris baru - 0x0A) valid dengan ketentuan bahwa:

  • Setiap kolom teks (vertikal) paling banyak berisi satu (dan ).
  • Mengabaikan posisi vertikal mereka, (dan )seimbang, yaitu masing (- masing dipasangkan dengan tepat )di sebelah kanannya, dan sebaliknya.

Tulis program atau fungsi yang, jika diberi string berisi ASCII yang dapat dicetak dan baris baru, menentukan apakah itu merupakan program Prelude yang valid. Anda dapat mengambil input melalui STDIN (atau alternatif terdekat), argumen baris perintah atau argumen fungsi. Hasilnya dapat dikembalikan atau dicetak ke STDOUT, menggunakan dua nilai kebenaran / kepalsuan tetap pilihan Anda.

Anda tidak boleh berasumsi bahwa input berbentuk persegi panjang.

Ini adalah kode golf, jadi pengiriman terpendek (dalam byte) menang.

Contohnya

Berikut ini adalah program Prelude yang valid (pada kenyataannya, mereka bahkan merupakan program Prelude yang nyata ):

?1-(v  #1)-             
1   0v ^(#    0)(1+0)#)!
    (#)  ^#1-(0 #       
1(#  1) v #  - 1+)
    vv (##^v^+
? v-(0 # ^   #)
?
  1+              1-!

Dan di sini ada sejumlah input, yang semuanya tidak valid :

#(#(##)##)##(
)##(##(##)#)#
#(#)
)###
#(##
(##)
(##)
(#)#
(##)
(###
#(#)
(##)
#(#)
###)
#()#
()##
#(#)##
###
###(#)
Martin Ender
sumber
Apakah Prelude memiliki komentar yang dapat memblokir paren dekat?
Alex A.
@Alex Tidak. Aturan di atas adalah benar-benar semua untuk memutuskan apakah suatu program valid atau tidak.
Martin Ender
Keren, terima kasih sudah menjelaskan. Hanya ingin memastikan.
Alex A.
Aturan 1 - "Setiap kolom teks berisi paling banyak satu (dan)"; Contoh 1, baris 2: "1 0v ^ (# 0) (1 + 0) #)!" -> Saya melihat 3 )dan 2 (. Bukankah seharusnya hanya 1 per baris?
Ismael Miguel
1
@IsmaelMiguel "kolom" biasanya dipahami untuk merujuk ke garis vertikal (terutama dalam konteks grid). Saya sudah mengklarifikasi hal itu.
Martin Ender

Jawaban:

3

CJam, 57 56 byte

qN/z_{_"()"--W<},,\s:Q,{)Q/({_')/,\'(/,-}:T~\sT0e>+z+}/!

Terlalu lama, bisa banyak bermain golf. Penjelasan yang akan ditambahkan begitu saya golf itu.

Penjelasan singkat

Ada dua cek dalam kode:

  • Filter pertama memeriksa bahwa setiap kolom paling banyak 1 braket. Output akhir dari filter adalah jumlah kolom dengan lebih dari 1 tanda kurung.
  • Kedua, kita mengonversi input menjadi format utama kolom dan kemudian membaginya pada setiap indeks menjadi dua bagian.
    • Di masing-masing dari dua bagian ini, ( Number of "(" - Number of ")") harus saling memuji. Jadi, ketika Anda menjumlahkannya, itu harus menghasilkan 0. Setiap bagian yang gagal properti ini membuat seluruh input memiliki tanda kurung yang tidak cocok.
    • Saya juga harus memastikan bahwa "(" ada di sebelah kiri ")". Ini berarti bahwa nilai Number of "(" - Number of ")"tidak boleh negatif untuk blok sisi kanan.

Cobalah online di sini

Pengoptimal
sumber
6

Python 2, 128 119 105 byte

def F(p):
 v=n=1
 for r in map(None,*p.split("\n")):A,B=map(r.count,"()");n+=B-A;v*=n<2>A+B
 return n*v>0

Tahukah Anda bahwa Anda dapat memetakan Tidak Ada dalam Python 2?

Penjelasan

Kami ingin memulai dengan mentransposisi Prelude sehingga kolom menjadi baris. Biasanya kita akan melakukan ini dengan zip, tetapi karena zipmemotong ke panjang baris terpendek dan itertools.zip_longestterlalu panjang untuk kode-golf, sepertinya tidak ada cara pendek untuk melakukan apa yang kita inginkan ...

Kecuali untuk pemetaan None:

>>> print map(None,*[[1,2,3],[4],[5,6]])
[(1, 4, 5), (2, None, 6), (3, None, None)]

Sayangnya (atau lebih tepatnya, untungnya untuk semua tujuan non-golf), ini hanya berfungsi di Python 2.

Adapun ndan v:

  • nbertindak seperti tumpukan, menghitung 1 - <number of unmatched '(' remaining>. Untuk setiap yang (kita lihat kita kurangi 1, dan untuk setiap yang )kita lihat kita tambahkan 1. Oleh karena itu jika n >= 2pada titik mana pun, maka kita telah melihat terlalu banyak )dan program tidak valid. Jika ntidak selesai pada 1, maka kami memiliki setidaknya satu yang (tersisa yang tidak cocok.
  • vmemeriksa validitas, dan mulai dari 1. Jika program tidak valid ( n >= 2atau A+B >= 2), maka vmenjadi 0 untuk menandai ketidakabsahan.

Karenanya jika program tersebut valid, maka pada akhirnya harus kita miliki n = 1, v = 1. Jika program tidak valid, maka pada akhirnya kita harus memiliki v = 0, atau v = 1, n <= 0. Oleh karena itu validitas dapat secara ringkas dinyatakan sebagai n*v>0.

(Terima kasih kepada @feersum untuk banyak saran bagus yang melepaskan 14 byte!)

Sebelumnya, pengiriman lebih mudah dibaca:

def F(p):
 p=map(None,*p.split("\n"));v=n=0
 for r in p:R=r.count;A=R("(");B=R(")");n+=A-B;v|=A+B>1or n<0
 return n<1>v
Sp3000
sumber
Itu penggunaan gila map...
xnor
1
119 -> 106def F(p): v=n=3 for r in map(None,*p.split("\n")):A,B=map(R.count,"()");n+=A-B;v*=n>2>A+B return n*v==9
feersum
@feersum Terima kasih! Aku telah mencoba untuk mengubah ormenjadi perbandingan chaining, tapi saya tidak berpikir untuk mengubah |=ke dalam *=.
Melepas
2

J, 64 byte

Input adalah string dengan baris baru yang tertinggal. Outputnya 0 atau 1.

(0=(1<|s)s+[:(|@{:+(0>])s)[:+/\]s=.+/@:)@(1 _1 0{~[:'()'&i.];.2)

Contoh penggunaan

   ]in=.'#(#)##',LF,'###',LF,'###(#)',LF
#(#)##
###
###(#)

   ((0=(1<|s)s+[:(|@{:+(0>])s)[:+/\]s=.+/@:)@(1 _1 0{~[:'()'&i.];.2)) in
0

Metodenya adalah sebagai berikut

  • memotong input pada baris baru dan dimasukkan ke dalam matriks ];.2
  • peta (/ )/ anything elseke 1/ -1/0 1 _1 0{~[:'()'&i.]
  • mendefinisikan s=.+/@:kata keterangan yang ditambahkan ke kata kerja meringkas output array kata kerja
  • tambahkan nilai dalam kolom ]s

    • periksa ()saldo positif di setiap awalan [:(0>])s)[:+/\]
    • periksa ()saldo yang sama di seluruh daftar (yaitu di awalan terakhir) |@{:@]
  • tambahkan abs (nilai) di kolom dan periksa setiap elemen untuk nilai maksimal 1 (1<|s)s

  • karena semua cek sebelumnya menghasilkan positif pada kegagalan, kami menjumlahkannya dan membandingkannya dengan 0 untuk mendapatkan validitas input 0=]

randomra
sumber
2

J, 56 byte

3 :'*/0<: ::0:(+/\*:b),-.|b=.+/+.^:_1]0|:''()''=/];.2 y'

Itu adalah fungsi anonim yang menerima string dengan baris baru tambahan dan mengembalikan 0 atau 1. Membaca dari kanan ke kiri:

  • ];.2 y, seperti pada pengajuan J lainnya, memotong string ysama sekali kemunculan karakter terakhirnya (itulah sebabnya input membutuhkan baris baru) dan membuat matriks persegi panjang yang barisnya adalah potongan-potongan, diisi dengan spasi jika perlu.

  • '()'=/membandingkan setiap karakter dalam matriks pertama dengan (dan kemudian dengan )mengembalikan daftar dua matriks 0-1.

  • +.^:_1]0|:mengubah daftar dua matriks menjadi matriks tunggal bilangan kompleks. Sejauh ini program mengubah setiap (input menjadi 1, setiap )menjadi i, dan setiap karakter lainnya menjadi 0.

  • b=.+/menugaskan jumlah baris dari matriks kompleks untuk b.

  • -.|bmembuat daftar 1- | z | untuk setiap z in b. Kondisi bahwa setiap kolom mengandung paling banyak tanda kurung tunggal diterjemahkan ke semua angka ini 1- | z | menjadi tidak negatif.

  • +/\*:badalah vektor menjalankan jumlah kuadrat dari angka dalam b. Jika setiap kolom berisi paling banyak satu tanda kurung, kuadrat angka dalam bsemua 0, 1 atau -1. The ,merangkai vektor ini dengan vektor 1- | z | 's.

  • sekarang semua yang perlu kita lakukan adalah menguji bahwa entri dari vektor gabungan kita vadalah angka asli non-negatif, ini hampir */0<:v, kecuali yang menyebabkan kesalahan jika beberapa entri vtidak nyata, jadi kita ganti <:dengan <: ::0:yang hanya mengembalikan 0 jika terjadi kesalahan .

Omar
sumber
Ide bagus dengan bilangan kompleks tetapi Anda juga perlu memeriksa apakah 0={:+/\*:bkarena mis. (Tidak valid.
randomra
Oh, kau benar, @randomra, aku lupa!
Omar
1
0=(-|)vlebih pendek 2 byte untuk memeriksa real non-negatif. (Ayo kalahkan CJam!: P)
randomra
1
Oh, dan invbukannya ^:_1 menyimpan byte lain.
randomra
1
Kembali ke 56 (dengan cek saldo): 3 :'*/0=({:,]-|)(-.@|,+/\@:*:)+/+.inv]0|:''()''=/];.2 y'.
randomra