Lakban Penentu Regex

11

Tugas Anda adalah membuat program yang menentukan apakah string yang diberikan adalah ekspresi reguler yang valid atau tidak menggunakan cuplikan kode yang bersumber dari situs di jaringan StackExchange.

Untuk keperluan tantangan ini, ekspresi dialek biasa akan menjadi set dipreteli dan sebagian besar minimal meta-karakter: ()*?|\. Dengan demikian, Anda tidak akan dapat menggunakan parser regex bawaan.

  • \digunakan untuk melarikan diri meta-karakter. Itu harus diikuti oleh meta-karakter.
  • Tanda kurung yang tidak dilepas harus seimbang
  • *dan ?harus didahului oleh karakter non-meta, grup dengan tanda kurung, atau karakter meta yang lolos.
  • Semua karakter ASCII yang dapat dicetak lainnya ditambah baris baru, tab, dan ruang harus didukung sebagai karakter non-meta. Apa yang terjadi dengan string yang berisi karakter lain tidak ditentukan.
  • Arti sebenarnya dari regex tidak penting untuk tantangan ini.

Contohnya

Truthy:
  abc
  a?
  (a|)*
  ()
  a|b*
  \*
  \\
  \\*
  a*b?(cd|e)
  +
  [
  }
  (123\))*
  \|
  (a(b(c|d)*e)*f)*
  (|\)*)
  (abc)+*
  (abc)+
  +abc

^ last test case is an actual newline

Falsy:
  ?abc
  *
  **
  \
  (
  a*?
  a?*
  ?
  a)
  (\)
  (|\)*
  \()
  |*
  (?:abc)
  \\**
  \n

Mencetak gol

Skor keseluruhan Anda adalah jumlah cuplikan yang diambil dari pertanyaan dan jawaban di sekitar StackExchange.

  • Cuplikan berulang dihitung sebanyak yang digunakan.
  • Ruang kosong dapat ditambahkan dan dihapus secara bebas (karena Python, Haskell, dan bahasa sensitif ruang putih lainnya) dan tidak diperhitungkan dalam jumlah cuplikan Anda.
    • Pengecualiannya adalah jika kode Anda benar-benar ditulis dalam Whitespace .
  • Cuplikan diperbolehkan dari situs StackExchange apa pun asalkan berasal dari pertanyaan, jawaban, dan komentar yang lebih lama (Termasuk dengan waktu edit - gunakan revisi yang lebih lama jika perlu) daripada tantangan ini. (24 Sep 2019 @ 15:30 UTC)
  • Cuplikan dapat datang dari mana saja dalam badan pertanyaan, jawaban, atau komentar, apakah itu dalam blok kode yang telah diformat sebelumnya atau tidak.
  • Menyambungkan snippet ke tengah yang lain menyebabkan snippet luar dihitung sebagai dua snippet

Menang skor terendah!

Beefster
sumber
1
@RobinRyder ya, berubah
Beefster
Dapatkah pos lebih tua dari atau sama dengan tantangan ini, yaitu dapatkah kita menggunakan cuplikan dari badan tantangan ini?
Jo King
1
"Dengan demikian, Anda tidak akan dapat menggunakan parser regex built-in" Apakah itu mengatakan bahwa itu dirancang untuk menggagalkan menggunakannya untuk ya / nay sederhana, atau bahwa kita dilarang menggunakan regex sama sekali dalam jawaban kami?
user0721090601
@guifa itu dirancang agar Anda tidak bisa begitu saja menggunakan mesin regex bahasa Anda dan melihat apakah ia mengkompilasi regex yang diberikan. Setiap bahasa yang saya tahu mendukung serangkaian besar meta-karakter dan kelompok tangkapan khusus, sehingga mereka tidak akan cocok dengan rangkaian karakter ini dengan benar dalam semua kasus.
Beefster
1
@ JL2210 Itu akan membuatnya menjadi dua cuplikan: satu untuk awal dan satu untuk akhir. Anda dapat menggunakan satu cuplikan selama melewati semua kasus uji dan berasal dari jawaban / pertanyaan / posting yang lebih tua dari tantangan ini
Beefster

Jawaban:

6

Perl 6 , 20 cuplikan

{$_ eq m/[[<-[()*?|\\]>|\\<[()*?|\\]>|'(' <~~>* ')']<[*?]>?|\|]+/}

Cobalah online!

Cuplikan diambil dari:

{$_ eq, m/[, <-[, ()*?, |\\, ]>, |\\, <[, ()*?, |\\, ]>, |, '(' <~~>* ')', <[, *?, ]>, ?|, \|, ]+/, }.

Ini sebagian besar pendekatan serakah (dibuat jelas oleh semua satu atau dua cuplikan karakter). Saya menggunakan SymbolHound untuk mencari masing-masing karakter, dan satu-satunya optimisasi nyata adalah '(' <~~>* ')'cuplikan, yang diambil dari jawaban saya sendiri pada regex Perl 6 rekursif.

Penjelasan:

Ini pada dasarnya memeriksa apakah input sama dengan kecocokan serakah dari regex yang valid. Alasan kami tidak bisa hanya menggunakan regex itu sendiri dan menambahkan ^$untuk menandai ujungnya adalah karena kami menggunakan regex rekursif, yang tidak akan berfungsi jika ada ^$marker. Regex itu sendiri adalah:

m/[                             ]+/   # Match one or more times
   [              ]  # Any of 
    <-[()*?|\\]> |     # Not a metacharacter
    \\<[()*?|\\]>      # A metacharacter preceded by a \
    '(' <~~>* ')'      # Brackets surrounding a valid regex
                   <[*?]>?  # Optionally followed by a ? or *
                           | \|    # Or just the | metacharacter
Jo King
sumber
TIL ~~, terima kasih!
user0721090601
@guifa Ya, saya mengetahui itu melalui spesifikasi P6 , yang memiliki banyak hal yang belum didokumentasikan dengan baik. Saya curiga ~~tidak muncul karena belum sepenuhnya diimplementasikan (misalnya <~~0>), meskipun ada permata tersembunyi lainnya di sana.
Jo King