Regex đơn giản ngắn nhất phù hợp với một từ nhị phân


20

Bài tập

Xác định một biểu thức chính đơn giản như một biểu thức chính quy không rỗng chỉ bao gồm

  • nhân vật 01,
  • nhóm dấu ngoặc đơn (),
  • định lượng lặp lại một hoặc nhiều +.

Đưa ra một chuỗi 0s và 1s không trống , chương trình của bạn sẽ tìm thấy biểu thức chính đơn giản ngắn nhất phù hợp với chuỗi đầu vào đầy đủ . (Nghĩa là, khi khớp với một biểu thức chính đơn giản, hãy giả vờ rằng nó bị vùi dập bởi ^ và  $.) Nếu có nhiều biểu thức chính ngắn nhất, hãy in bất kỳ hoặc tất cả chúng.)

, vì vậy bài nộp ngắn nhất (tính bằng byte) sẽ thắng.

Các trường hợp thử nghiệm

1 -> 1
00 -> 00 or 0+
010 -> 010
1110 -> 1+0
01010 -> 01010
0101010 -> 0(10)+ or (01)+0
011111 -> 01+
10110110 -> (1+0)+
01100110 -> (0110)+ or (01+0)+
010010010 -> (010)+
111100111 -> 1+001+ or 1+0+1+
00000101010 -> 0+(10)+ or (0+1)+0
1010110001 -> 1(0+1+)+ or (1+0+)+1

3
Bạn nên làm rõ rằng bạn muốn chúng tôi viết một chương trình viết regex chứ không phải viết regex our own. Nhưng điều này có vẻ thú vị.
gcampbell

1
Trong thử nghiệm của tôi, 01100110là một trường hợp thú vị ... một thuật toán ngây thơ sẽ viết 01+0+1+0hoặc (0+1+)+0không tối ưu.
Neil

Câu trả lời:


2

Bình thường, 20 byte

hf.x}z:zT1Zy*4"()01+

Điều này mất khoảng 30 giây để chạy, vì vậy nó cần được chạy ngoại tuyến.

Giải trình:

hf.x}z:zT1Zy*4"()01+
                        Implicit: z is the input string.
              "()01+    "()01+"
            *4          Repeated 4 times
           y            All subsequences in length order
hf                      Output the first one such that
      :zT1              Form all regex matches of z with the candidate string
    }z                  Check if the input is one of the strings
  .x      Z             Discard errors

Tôi không hoàn toàn chắc chắn rằng mọi chuỗi ngắn nhất là một chuỗi "() 01+" * 4, nhưng 4 có thể tăng lên 9 mà không mất chi phí byte nếu cần.


9

JavaScript (ES6), 488 341 byte

s=>[s.replace(/(.)\1+/g,'$1+'),...[...Array(60)].map((_,i)=>`(${(i+4).toString(2).slice(1)})+`),...[...Array(1536)].map((_,i)=>`${i>>10?(i>>8&1)+(i&2?'+':''):''}(${i&1}${i&4?i>>4&1:i&16?'+':''}${i&8?''+(i>>7&1)+(i&64?i>>5&1:i&32?'+':''):''})+${i&512?(i>>8&1)+(i&2?'+':''):''}`)].filter(r=>s.match(`^${r}$`)).sort((a,b)=>a.length-b.length)[0]

Giải thích: Vì sáu biểu thức có thể diễn tả tất cả các từ nhị phân có thể và hai từ dài nhất có chín ký tự, nên đủ để kiểm tra các từ đó và tất cả các biểu thức ngắn hơn. Một ứng cử viên rõ ràng là chuỗi có "mã hóa chiều dài chạy" (nghĩa là tất cả các chữ số chạy được thay thế bằng +s thích hợp ), nhưng cũng ()phải kiểm tra các chuỗi có một bộ s. Tôi tạo ra 1596 regex như vậy (điều này bao gồm các bản sao và regex vô dụng nhưng chúng sẽ bị loại bỏ) và kiểm tra tất cả 1597 để xem đâu là trận đấu ngắn nhất. Các biểu thức được tạo ra rơi vào hai loại: \(\d{2,5}\)\+(60 biểu thức chính) và (\d\+?)?\(\d[\d+]?(\d[\d+]?)?\)(\d\+?)?(1536 biểu thức chính vì tôi tránh tạo các biểu thức chính có cả chữ số đầu và cuối).


@LeakyNun Ban đầu tôi nghĩ có 4 regex có độ dài 9 nhưng điều này rõ ràng là không chính xác nên tôi đã làm rõ lời giải thích của mình.
Neil


1

Ruby, 109 byte

Đó là cách tiếp cận vũ phu nhàm chán. Hoạt động vì không có regex nào cần dài hơn 9 ký tự (như Neil lưu ý) và không có ký tự riêng lẻ nào cần lặp lại quá 4 lần (thử với '01()+'.chars*9CPU khiến tôi không hài lòng).

10.times{|i|('01()+'.chars*4).combination(i).map{|s|begin
/^#{s*''}$/=~$*[0]&&[puts(s*''),exit]
rescue
end}}
$ for word in `grep -Po '^\S+' test_cases.txt`; do nice -n20 ruby sre.rb $word; done
1
0+
010
1+0
01010
0(10)+
01+
(1+0)+
(01+0)+
(010)+
1+0+1+
0+(10)+
1(0+1+)+

1

Python 3, 186 byte

Tôi đang điều tra xem liệu có một cách tiếp cận cho vấn đề này ngoài việc cưỡng bức vũ phu hay không, nhưng bây giờ đây là một giải pháp vũ phu của Python.

import re,itertools
def a(b):
 for z in range(10):
  for i in itertools.combinations("01()+"*4,z):
   j=''.join(i)
   try:
    if re.fullmatch(j,b)and len(j)<=len(b):return j
   except:1
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.