Biên dịch Regexes (Theo thay thế)


21

Nhiệm vụ của bạn là biên dịch regexes ... bằng cách chỉ định thay thế cho mỗi ký tự trong regex.

Chế độ

Các regexes hỗ trợ những

REGEX       = (LITERAL REGEX / GROUP REGEX / STAR REGEX / ALTERNATIVE)
LITERAL     = 1 / 0
GROUP       = '(' REGEX ')'
STAR        = (LITERAL / GROUP) '*'
ALTERNATIVE = '('REGEX ('|' REGEX)*')'

Tại sao chỉ có 1 hoặc 0? Nó là để đơn giản hóa. Do đó, regex chỉ có các ký tự sau:

*()|10

Nó được giải thích như sau:

  1. * là ngôi sao Kleene (lặp lại nhóm trái hoặc nghĩa đen 0 lần trở lên).
  2. | là sự xen kẽ (khớp nếu regex ở bên trái hoặc regex ở bên phải khớp).
  3. () đang nhóm lại.
  4. 1 phù hợp với nhân vật 1.
  5. 0 khớp với ký tự 0.

Làm thế nào để biên dịch?

Bạn chỉ định sáu đoạn mã: một để thay thế mỗi ký tự regex. Ví dụ: nếu câu trả lời của bạn là:

*: FSAGFSDVADFS
|: GSDGSAG
(: GSDG
): GDSIH
1: RGIHAIGH
0:GIHEBN

Sau đó, bạn thay thế mỗi regex bằng đoạn mã tương ứng của nó, vì vậy:

(0|11)*

được biến thành:

GSDGGIHEBNGSDGSAGRGIHAIGHRGIHAIGHGDSIHFSAGFSDVADFS

Chương trình kết quả phải làm là gì?

Chương trình của bạn sẽ:

  1. Lấy đầu vào.
  2. Xuất ra một giá trị trung thực nếu regex khớp với toàn bộ đầu vào.
  3. Khác đầu ra một giá trị giả.

Đầu vào bên ngoài 01được coi là hành vi không xác định. Đầu vào có thể trống.

Quy tắc bổ sung

  1. Đối với một ký tự regex đã cho, đoạn kết quả phải luôn giống nhau.
  2. Không có tiền tố hoặc ký tự hậu tố được thêm vào sau đó.
  3. Regex được đảm bảo là không trống.

Chấm điểm

Đoạn kết hợp ít nhất là người chiến thắng. Vì vậy, điểm cho trường hợp ví dụ sẽ được tính như sau:

FSAGFSDVADFS+ GSDGSAG+ GSDG+ GDSIH+ RGIHAIGH+GIHEBN

12 + 7 + 4 + 5 + 8 + 6 = 42


Là mỗi đoạn mã dài ít nhất 1 ký tự?
trichoplax

Đoạn mã có thể có độ dài bằng không. Chỉnh sửa là OK.
Akangka

Ngôn ngữ RegEx có hợp lệ cho thử thách này không? : P
Loovjo

Tôi coi RegEx có tích hợp RegEx. Tôi buộc phải làm điều này. Tôi muốn loại trừ Retina và regex, tuy nhiên, theo Mego, điều đó không được phép. Tuy nhiên, tôi không biết về Ốc và bạn bè.
Akangka

@ChristianIrwan Thật thú vị, tôi vẫn không chắc điều này thậm chí có thể giải quyết được ở Retina, và thậm chí nó còn không thể cạnh tranh được.
Martin Ender

Câu trả lời:


7

Ốc , 48 byte

0 -> )0(\0!(l.)(~

1 -> )0(\1!(l.)(~

( -> )0({{(

) -> )0}}(~

| -> )0}|{(

* -> )0),(~

Nếu chúng ta phải tìm kiếm các phần trùng khớp thay vì chỉ khớp với đầu vào đầy đủ, thì nó sẽ rất dễ dàng. 0sẽ trở thành \0, 1sẽ trở thành \1, *sẽ trở thành ,và những người khác sẽ lập bản đồ cho chính họ. Thay vào đó, có rất nhiều shenanigans để ngăn các trận đấu bắt đầu ở một nơi khác ngoài bắt đầu hoặc kết thúc ở một nơi khác ngoài kết thúc. !(l.)là một khẳng định sẽ thất bại nếu bắt đầu trận đấu không ở đầu của đầu vào. ~khớp với một ô bên ngoài đầu vào, vì vậy nó được thêm vào tất cả các ký tự được phép ở cuối regex. Nếu có một ký tự regex khác theo sau, nó sẽ bị hủy bởi bộ định lượng số0trong đó yêu cầu nó phải được khớp 0 lần, về cơ bản là nhận xét nó. Để cho phép *( ,) hoạt động chính xác mặc dù thử nghiệm ngoài giới hạn đang được thực hiện, các quy tắc khớp khung của ngôn ngữ được sử dụng rất nhiều. Từ tài liệu:

Các cặp dấu ngoặc đơn ()hoặc dấu ngoặc nhọn {}sẽ hoạt động như mong đợi (như dấu ngoặc đơn trong regex), nhưng cũng có thể bỏ qua một nửa của cặp và suy ra, theo các quy tắc sau. )hoặc }nhóm mọi thứ ở bên trái cho đến khi hướng dẫn mở nhóm không được tiết lộ gần nhất cùng loại ( (hoặc {tương ứng), hoặc bắt đầu mẫu nếu không tồn tại. Nó đóng bất kỳ hướng dẫn mở không được tiết lộ của loại đối diện ở giữa phạm vi này. Một cách khác chưa từng có (hoặc {được đóng vào cuối mẫu.

Rõ ràng như bùn, phải không?


Thở dài, tôi quên rằng thậm chí còn có ngôn ngữ phù hợp bên ngoài regex. Công việc tốt, nhưng xin lỗi, không có upvote (cũng không có downvote)
Akangka

@ChristianIrwan thực sự có một thách thức toàn bộ trên trang web này để phát triển các ngôn ngữ phù hợp 2d, hầu hết trong số đó có sử dụng thoái hóa 1d. codegolf.stackexchange.com/questions/47311/ từ
Sparr

7

CJam, 151 byte

{]Na/Saf+{:m*:sSf-~}%}:J{+:MU{]W=~Jea&,}|}:TM0sa`T
{]Na/Saf+{:m*:sSf-~}%}:J{+:MU{]W=~Jea&,}|}:TM1sa`T
M{{+:M];eas!}:T}|U):UM'[T
MN`T
U(:UM'JT
M\"S+ea`,m*\"T

Các dòng tương ứng với các ký tự 01(|)*(theo thứ tự đó). Hãy thử trực tuyến!

Điều này không sử dụng biểu thức chính quy tích hợp hoặc các kiểu khớp mẫu khác. Trong thực tế, CJam không có những tính năng này. Thay vào đó, nó bắt đầu từ biểu thức chính quy mà nó biểu thị và xây dựng tất cả các chuỗi có thể khớp với nó , để cuối cùng kiểm tra xem đầu vào của người dùng có phải là một trong số chúng không.

Chạy thử

Phần sau đây sử dụng chương trình đọc biểu thức chính quy từ STDIN, thay thế từng ký tự của nó bằng đoạn mã thích hợp và cuối cùng đánh giá mã được tạo để xem liệu nó có khớp với đầu vào được chỉ định trong đối số dòng lệnh hay không.

$ cat regex.cjam
l"01(|)*""

{]Na/Saf+{:m*:sSf-~}%}:J{+:MU{]W=~Jea&,}|}:TM0sa`T
{]Na/Saf+{:m*:sSf-~}%}:J{+:MU{]W=~Jea&,}|}:TM1sa`T
M{{+:M];eas!}:T}|U):UM'[T
MN`T
U(:UM'JT
M\"S+ea`,m*\"T

"N%ers~
$ cjam regex.cjam '' <<< '(|)'
1
$ cjam regex.cjam '0' <<< '(|)'
0
$ cjam regex.cjam '' <<< '0(|)'
0
$ cjam regex.cjam '0' <<< '0(|)'
1
$ cjam regex.cjam '' <<< '(0|11)*'
1
$ cjam regex.cjam '0' <<< '(0|11)*'
1
$ cjam regex.cjam '11' <<< '(0|11)*'
1
$ cjam regex.cjam '011011000' <<< '(0|11)*'
1
$ cjam regex.cjam '1010' <<< '(0|11)*'
0

Thật không may, điều này không đặc biệt nhanh. Nó sẽ bị nghẹt khá nhanh nếu có nhiều hơn 9 ký tự trong đầu vào hoặc nhiều hơn một ngôi sao Kleene trong regex.

Với chi phí là 5 byte bổ sung - với tổng số 156 byte - chúng ta có thể tạo các chuỗi ngắn hơn để khớp với đầu vào tiềm năng và sao chép chúng. Điều này không thay đổi cách mã hoạt động; nó chỉ làm cho nó hiệu quả hơn

$ cat regex-fast.cjam 
l"01(|)*""

{]Na/Saf+{:m*:sSf-~}%}:J{+:MU{]W=~Jea&,}|}:TM0sa`T
{]Na/Saf+{:m*:sSf-~}%}:J{+:MU{]W=~Jea&,}|}:TM1sa`T
M{{+:M];eas!}:T}|U):UM'[T
MN`T
U(:UM'JT
M\"S+eas,)m*:sSf-L|\"T

"N%ers~
$ cjam regex-fast.cjam '0101001010' <<< '(01|10)*'
0
$ cjam regex-fast.cjam '011001101001' <<< '(01|10)*'
1
$ cjam regex-fast.cjam '0' <<< '(0*1)*'
0
$ time cjam regex-fast.cjam '101001' <<< '(0*1)*'
1

Tôi vẫn có một số ý tưởng làm thế nào tôi có thể làm cho điều này ngắn hơn và / hoặc nhanh hơn. Tôi sẽ thêm một lời giải thích khi tôi hài lòng với kết quả.
Dennis

Dường như có một `-escaping of the "` trong mẫu cho *. Bất kể điều đó, tôi không thể khiến chương trình này chấp nhận bất kỳ đầu vào nào, ngay cả trong trường hợp đơn giản nhất mà regex chỉ bao gồm một 0(xem thử trong trình thông dịch trực tuyến ). Tôi làm sai?
matz

1
@matz Mã của tôi sử dụng các đối số dòng lệnh, không được triển khai trong trình thông dịch đó. Hãy thử cái này thay thế.
Dennis
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.