Regex cho bội số của 9


14

Thật dễ dàng để mô tả một máy trạng thái hữu hạn có thể nhận ra bội số của 9: theo dõi tổng số chữ số (mod 9) và thêm bất kỳ chữ số nào được chấp nhận tiếp theo. Một FSM như vậy chỉ có 9 tiểu bang, rất đơn giản! Bằng sự tương đương giữa khả năng nhận biết của FSM và các ngôn ngữ thông thường, có một biểu thức chính quy cho bội số 9. Tuy nhiên, bất kỳ biểu thức chính quy nào như vậy có khả năng ... rất ... dài. Như trong, có khả năng theo thứ tự của một gigabyte.

Có một ví dụ hoạt động tại https://www.quaxio.com/triple/ cho bội số của 3. Ở cuối trang, tác giả cung cấp giải pháp hơi "tối ưu hóa bằng tay" ngắn hơn một chút so với chuyển đổi ngây thơ từ FSM để regex.

Các thách thức:

Bạn phải tạo một regex để phát hiện bội số của 9. Vì một regex như vậy dự kiến ​​sẽ rất dài, tôi yêu cầu bạn cung cấp một chương trình có thể in ra regex của bạn. (Nếu bạn thực sự muốn cung cấp toàn bộ regex, có thể lưu trữ nó ở nơi khác và liên kết nó ở đây!)

Bạn phải có thể cho chúng tôi biết số lượng ký tự chính xác của đầu ra chương trình của bạn - vì vậy, có một chương trình chỉ đơn giản là thử tất cả các biểu thức có độ dài nhất định, cho đến khi tìm thấy một hoạt động, không thể chấp nhận được trừ khi nó chạy đủ nhanh để bạn có thể chạy nó để hoàn thành và cung cấp cho chúng tôi độ dài regex kết quả!

Điểm là để có regex đầu ra ngắn nhất, tất nhiên không dựa trên thời lượng chương trình. Vì regex là "chương trình" mà tôi đang yêu cầu và nó quá dài để truyền tải thuận tiện ở đây, nên tôi vẫn gắn thẻ môn đánh gôn này.

Quy tắc:

  • Đầu vào sẽ chỉ bao gồm các ký tự khớp [0-9]*.
  • Regex của bạn phải phù hợp với bội số của 9, nhưng không phải bất cứ điều gì khác. Các trường hợp không được tạo hoàn toàn bằng các chữ số 0-9 và là đầu vào không hợp lệ có thể khớp hoặc thất bại như bạn muốn.
  • Với động lực mà DFA dễ dàng nhận ra, regex kết quả thực sự phải là biểu thức chính quy theo thuật ngữ lý thuyết hơn, nghĩa là chỉ các toán tử theo đó các ngôn ngữ thông thường được đóng. Nói chính xác, những điều duy nhất được phép:
    • Literals, dãy ký tự ( [ab], [a-f], [^k]), ngôi sao Kleene ( *), neo ( ^$), nhóm thông qua dấu ngoặc đơn, thay đổi luân phiên ( |), điều khoản bắt buộc ( ?), một-hay-hơn các điều khoản ( +), lookaheads ( (?=)), lookaheads tiêu cực ( (?!)), lookbehinds ( (?<=)), lookbehinds ( (?<!)), điều kiện tiêu cực (như trong https://www.THER-expressions.info/conditable.html - (?(?=test)then|else)) và phản hồi có độ dài giới hạn (xem bên dưới).
  • Ví dụ về những điều không được phép:
    • Phản hồi về độ dài tùy ý, tham chiếu chuyển tiếp, đệ quy, chương trình con, cấu trúc lặp, mã thực thi, bất kỳ biến thể nào của 'eval' hoặc cấu trúc dựng sẵn để truyền chuỗi thành giá trị số học.
  • Backreferences có thể được hiển thị để có một chuỗi ràng buộc có độ dài giới hạn có thể được chấp nhận, vì chúng có thể được lưu trữ ở trạng thái hữu hạn và không làm thay đổi tính thường xuyên của ngôn ngữ. Ví dụ, regex (..2.[3-5])4\1.\1có thể chấp nhận được, vì có độ dài ràng buộc trên nhóm chụp \1. Đây là một công trình thường xuyên. Một cấu trúc như (2*)0\1không được chấp nhận, vì nhóm bị bắt không thể được lưu trữ ở trạng thái hữu hạn.
  • Regex của bạn được tự do chấp nhận hoặc từ chối các số nguyên với các số 0 đứng đầu ngoài ý muốn. Tuy nhiên, chuỗi "0"phải được chấp nhận.

2
Liên quan , không chắc chắn nếu điều này được coi là trùng lặp
ASCII

À, ừm! Tôi đã tìm kiếm "regex bội" nhưng không "regex chia hết". Tôi cho rằng điều đó rất giống nhau, vâng.
Alex Meiburg

11
Vẫn chưa được nói, vì vậy Chào mừng bạn đến với PPCG và thử thách đầu tiên thú vị! Như được đề cập bởi một người dùng khác, thường được đề xuất, nhưng không bắt buộc, để đăng các đề xuất thách thức trong Sandbox để họ có thể nhận phản hồi, trước khi đăng lên chính. Tuy nhiên, đây là một thử thách được cân nhắc kỹ lưỡng và rõ ràng, vì vậy không có lý do gì để chuyển điều này sang Sandbox. Hy vọng bạn thích cộng đồng của chúng tôi!
caird coinheringaahing

Các giải pháp có ít hơn 200 kibibytes là có thể, vì vậy nó sẽ không lớn lắm
TonMedel

3
Giải pháp sử dụng tiện ích mở rộng của .NET:^(0|9|(?<c>1|(?<c>2|(?<c>3|(?<c>4|(?<c>5|(?<c>6|(?<c>7|(?<c>8))))))))((?<-c>){9})?)*$(?(c).)
Neil

Câu trả lời:


3

Haskell , 207,535 202,073 byte

5.462 byte được lưu bằng cách sử dụng 0|9thay vì [09]khi có thể.

digits n
  | x == 0    = "0|9"
  | otherwise = show x
  where x = mod n 9

regex 0 = "[09]*"
regex n = (regex' n (-1) (-1)) ++ "*"

regex' 0 start end = digits (end - start)
regex' n start end = '(':(regex' 0 start end) ++ (concat ['|':(regex' (n-x) (start-x) (-1)) ++ (regex (n-x))
                                                  ++ (regex' (n-x) (-1) (end-x)) | x <- [1..n]]) ++ ")"

main = do
  putStr ("^" ++ (regex 8) ++ "$")

Hãy thử trực tuyến!

Chỉ cần một bản chuyển thể nhanh của regex được đưa ra trong phần chú thích của bài viết được liên kết để bắt đầu mọi thứ.

Pastebin của regex đầu ra , lịch sự của Herman Lauenstein.

Mặc dù tôi chưa thể kiểm tra regex đầy đủ, nhưng sửa đổi chương trình để kiểm tra mức chia hết cho 3 thay vào đó sẽ đưa ra một cái gì đó chính xác tương đương với regex mà tôi dựa trên này. Hơn nữa, sửa đổi chương trình để kiểm tra tính chia hết của chữ số bằng 4 hoặc 5 dường như cũng hoạt động trên các số tôi đã kiểm tra.


Bạn cũng có thể kiểm tra xem phương thức của bạn mang lại khả năng chia hết cho 2 (nên giống như thế nào /even$/) và chia hết cho 5 (nên giống như vậy /[05]$/). Tái
bút

Đây là một pastebin với đầu ra (với tất cả các lần xuất hiện được ([09]|thay thế bằng (0|9|để tiết kiệm hàng nghìn byte)
Herman L
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.