Đây rõ ràng là ngôn ngữ phù hợp cho nhiệm vụ. : ^ D
s:({c<L>}{c<R>}0[(<R> <L>)(<L> <R>)_?])%{30}
c:0 *$
Khớp với toàn bộ đầu vào nếu nó là một con rắn hợp lệ; không phù hợp nếu không. Hãy thử nó ở đây!
Giải trình
SnakeEx là một ngôn ngữ khớp mẫu 2 chiều . Một chương trình bao gồm một danh sách các định nghĩa cho "rắn", chúng bò xung quanh các ký tự khớp đầu vào, thay đổi hướng và sinh ra các con rắn khác. Trong chương trình của chúng tôi, chúng tôi xác định hai con rắn s
và c
.
Chúng ta sẽ bắt đầu với c
vì nó đơn giản hơn. Định nghĩa của nó là 0 *$
, sẽ khá dễ đọc nếu bạn biết regex: match 0
, theo sau là 0 hoặc nhiều khoảng trắng, theo sau là cạnh của lưới. Bắt chính ở đây: kết hợp này có thể tiến hành theo bất kỳ hướng nào. Chúng tôi sẽ sử dụng c
cả lên và xuống từ con rắn, để xác minh rằng không có thêm 0
s trong mỗi cột.
Bây giờ cho con rắn chính s
,. Nó có dạng (...)%{30}
, có nghĩa là "khớp với nội dung của dấu ngoặc đơn 30 lần" - một lần cho mỗi 0
con rắn. Càng xa càng tốt. Những gì đi trong dấu ngoặc đơn?
{c<L>}
Điều này sinh ra một c
con rắn mới , quay trái 90 độ. Hướng này liên quan đến s
hướng của con rắn, vì vậy con rắn mới di chuyển về phía trên cùng của lưới (con rắn chính đang di chuyển về phía bên phải). Con c
rắn kiểm tra rằng ô lưới hiện tại là một 0
và mọi ô phía trên nó là một khoảng trắng. Nếu thất bại, toàn bộ trận đấu thất bại. Nếu nó thành công, chúng tôi tiếp tục với
{c<R>}
mà làm điều tương tự, chỉ rẽ phải (về phía dưới cùng của lưới).
Lưu ý rằng những sinh sản này không ảnh hưởng đến vị trí của con trỏ khớp trong con rắn chính. Chúng hơi giống như những cái nhìn trong regex. (Có lẽ ở đây chúng ta có thể gọi chúng là "lookbesides"?) Vì vậy, sau khi xác minh rằng chúng ta đang chỉ đến một 0
và phần còn lại của cột chỉ chứa khoảng trắng, chúng ta cần thực sự khớp với 0
:
0
Bây giờ con trỏ khớp nằm trên ký tự bên phải của 0
. Chúng ta cần kiểm tra ba tùy chọn khác nhau: con rắn nghiêng xuống, con rắn hướng lên hoặc con rắn đi thẳng. Đối với điều này, chúng ta có thể sử dụng biểu thức OR:
[...]
Trong OR của chúng tôi, chúng tôi có ba khả năng:
(<R> <L>)
Rẽ phải, khớp với một khoảng trắng và rẽ trái lần nữa (góc rắn xuống).
(<L> <R>)
Rẽ trái, khớp một khoảng trắng và rẽ phải lần nữa (góc nghiêng lên).
_?
Khớp 0 hoặc một dấu gạch dưới. Vì không có dấu gạch dưới trong đầu vào, đây sẽ luôn là một kết quả trống (con rắn đi thẳng).
Sau khi khớp một trong ba tùy chọn ở trên, con trỏ khớp sẽ được trỏ đến 0
cột trong cột tiếp theo, sẵn sàng khớp lại biểu thức được ngoặc đơn.