Regex Golf: Xác minh giải pháp Sudoku


65

Viết một biểu thức chính phù hợp với bất kỳ giải pháp sudoku hợp lệ nào và không khớp với bất kỳ giải pháp sudoku không hợp lệ nào. Đầu vào là một trải ra phiên bản của sudoku, tức là không có delimiters dòng. Ví dụ: bảng sau:

7 2 5 8 9 3 4 6 1
8 4 1 6 5 7 3 9 2
3 9 6 1 4 2 7 5 8
4 7 3 5 1 6 8 2 9
1 6 8 4 2 9 5 3 7
9 5 2 3 7 8 1 4 6
2 3 4 7 6 1 9 8 5
6 8 7 9 3 5 2 1 4
5 1 9 2 8 4 6 7 3

sẽ được đưa ra như:

725893461841657392396142758473516829168429537952378146234761985687935214519284673

Các quy tắc có thể là kiến ​​thức phổ biến cho đến bây giờ, nhưng chỉ trong trường hợp ... một bảng sudoku là hợp lệ khi và chỉ khi:

  • Mỗi hàng chứa các chữ số từ 1đến 9đúng một lần.
  • Mỗi cột có chứa các chữ số từ 1đến 9đúng một lần.
  • Mỗi phòng trong số chín subgrids 3x3 chứa các chữ số từ 1đến 9đúng một lần.

Quy tắc

Câu trả lời của bạn nên bao gồm một regex duy nhất, không có bất kỳ mã bổ sung nào (ngoại trừ, tùy chọn, một danh sách các sửa đổi regex cần thiết để làm cho giải pháp của bạn hoạt động). Bạn không được sử dụng các tính năng của hương vị regex của ngôn ngữ cho phép bạn gọi mã bằng ngôn ngữ lưu trữ (ví dụ: công cụ esửa đổi của Perl ).

Bạn có thể sử dụng bất kỳ hương vị regex nào tồn tại trước thử thách này, nhưng vui lòng chỉ định hương vị.

Đừng cho rằng regex được neo hoàn toàn. Ví dụ: nếu bạn đang sử dụng Python, giả sử rằng regex của bạn được sử dụng re.searchvà không sử dụng re.match. Regex của bạn không cần phải khớp với toàn bộ chuỗi. Nó chỉ cần khớp ít nhất một chuỗi con (có thể trống) cho các giải pháp hợp lệ và không mang lại kết quả khớp nào cho các giải pháp không hợp lệ.

Bạn có thể cho rằng đầu vào sẽ luôn là một chuỗi gồm 81 chữ số dương.

Đây là regex golf, vì vậy regex ngắn nhất tính bằng byte thắng. Nếu ngôn ngữ của bạn yêu cầu các dấu phân cách (thông thường /.../) để biểu thị các biểu thức chính quy, đừng đếm chính các dấu phân cách. Nếu giải pháp của bạn yêu cầu sửa đổi, hãy thêm một byte cho mỗi sửa đổi.

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

Bảng hợp lệ:

123456789456789123789123456231564897564897231897231564312645978645978312978312645
725893461841657392396142758473516829168429537952378146234761985687935214519284673
395412678824376591671589243156928437249735186738641925983164752412857369567293814
679543182158926473432817659567381294914265738283479561345792816896154327721638945
867539142324167859159482736275398614936241587481756923592873461743615298618924375
954217683861453729372968145516832497249675318783149256437581962695324871128796534
271459386435168927986273541518734269769821435342596178194387652657942813823615794
237541896186927345495386721743269158569178432812435679378652914924813567651794283
168279435459863271273415986821354769734692518596781342615947823387526194942138657
863459712415273869279168354526387941947615238138942576781596423354821697692734185
768593142423176859951428736184765923572389614639214587816942375295837461347651298
243561789819327456657489132374192865926845317581673294162758943735914628498236571
243156789519847326687392145361475892724918653895263471152684937436729518978531264
498236571735914628162758943581673294926845317374192865657489132819327456243561789
978531264436729518152684937895263471724918653361475892687392145519847326243156789
341572689257698143986413275862341957495726831173985426519234768734869512628157394

Bảng không hợp lệ:

519284673725893461841657392396142758473516829168429537952378146234761985687935214
839541267182437659367158924715692843624973518573864192298316475941285736456729381
679543182158926473432817659567381294914256738283479561345792816896154327721638945
867539142324167859159482736275398684936241517481756923592873461743615298618924375
754219683861453729372968145516832497249675318983147256437581962695324871128796534
271459386435168927986273541518734269769828435342596178194387652657942813823615794
237541896186927345378652914743269158569178432812435679495386721924813567651794283
168759432459613278273165984821594763734982516596821347615437829387246195942378651
869887283619214453457338664548525781275424668379969727517385163319223917621449519
894158578962859187461322315913849812241742157275462973384219294849882291119423759
123456789456789123564897231231564897789123456897231564312645978645978312978312645
145278369256389147364197258478512693589623471697431582712845936823956714931764825
243561789829317456657489132374192865916845327581673294162758943735924618498236571
243156789529847316687392145361475892714928653895263471152684937436719528978531264
498236571735924618162758943581673294916845327374192865657489132829317456243561789
978531264436719528152684937895263471714928653361475892687392145529847316243156789
342571689257698143986413275861342957495726831173985426519234768734869512628157394
345678192627319458892451673468793521713524986951862347179246835534187269286935714
341572689257698143986413275862341957495726831173985426519234768734869512628517394

Đối với các trường hợp thử nghiệm tiếp theo, bạn có thể sử dụng tập lệnh CJam này lấy một bảng hợp lệ làm đầu vào và xáo trộn ngẫu nhiên để đưa ra một bảng hợp lệ mới (định dạng đầu vào không liên quan miễn là nó chỉ chứa các chữ số và khoảng trắng tùy chọn).

Nếu regex của bạn tương thích với hương vị .NET, bạn có thể kiểm tra trực tuyến bằng Retina. Một giải pháp hợp lệ nên in 0cho bảng không hợp lệ và một số số nguyên dương cho bảng hợp lệ. Để chạy tất cả các trường hợp thử nghiệm cùng một lúc, hãy sử dụng mẫu này và chèn regex trên dòng thứ hai. Nếu bạn cần công cụ sửa đổi regex, hãy thêm a `vào regex và đặt các chữ cái sửa đổi tiêu chuẩn ở phía trước nó.



1
Nếu chỉ đây là [code-bowling], lol.
mbomb007

Đợi ... Nếu chúng ta đang sử dụng Python, chúng ta chỉ có thể sử dụng các biểu thức thông thường, và không có gì khác? Ngoài ra, mỗi bảng lớn như thế nào? Có một kích thước cụ thể? Nếu không, chúng ta nên trích xuất từng bảng ra khỏi cụm chữ số dưới đây valid boardsnhư thế nào?
R. Kap

@ R.Kap Bất kể bạn đang sử dụng hương vị nào, bạn chỉ nên gửi regex (và có thể một số sửa đổi), vâng. Mỗi đầu vào chính xác là 81 chữ số và thể hiện một bảng đầy đủ. (Mỗi dòng trong các trường hợp thử nghiệm là một bảng riêng biệt.)
Martin Ender

Tôi đã viết một kịch bản để giải các sudoku đơn giản trong SQL. Tôi chắc chắn rằng nó có thể được viết lại cho câu hỏi này. Tuy nhiên, SQL không có nhiều REGEX. Điều đó không đủ điều kiện trả lời? (Tập lệnh có thể sẽ thấp hơn 400 ký tự một chút)
t-clausen.dk

Câu trả lời:


40

Ruby regex, 71 78 73 byte

^(?!.*(?=(.))(.{9}+|(.(?!.{9}*$))+|(?>.(?!.{3}*$)|(.(?!.{27}*$)){7})+)\1)

Tôi thực sự không biết Ruby nhưng dường như nó không phàn nàn về các bộ lượng hóa xếp tầng.

Hãy thử nó ở đây.

.NET regex, 79 78 75 hoặc 77 byte

Bởi vì Martin nghĩ rằng điều này là có thể ... Nhưng tôi đoán anh ấy cũng sẽ kết hợp những thay đổi này.

^(?!(.)+((.{9})+|(?>(.{9})+
|.)+|(?((...)*
)(?>(.{27})+
|.){7}|.)+)(?<=\1))

Yêu cầu một dòng mới trong đầu vào để làm việc. Tôi không chắc liệu tôi có được phép làm điều này không (có lẽ là không).

Hãy thử nó ở đây.

Phiên bản lành mạnh 77 byte:

^(?!(.)+((.{9})+|((?!(.{9})*$).)+|(?((...)*$)((?!(.{27})*$).){7}|.)+)(?<=\1))

Cảm ơn Neil vì đã chỉ ra lỗi trong phiên bản trước của tôi và bỏ đi 1 byte (đối với (...)*).

Hãy thử nó ở đây.

PCRE, 77 78 byte

^(?!.*(?=(.))((.{9})+|(.(?!(?3)*$))+|(?(?=.(...)*$)(.(?!(.{27})*$)){7}|.)+)\1)

Chỉ cần cho đầy đủ.

Hãy thử nó ở đây.

Một phiên bản khác, cũng là 78 ​​byte:

^(?!.*(?=(.))((.{9})+|(.(?!(?3)*$))+|(?>.(?!(...)*$)|(.(?!(.{27})*$)){7})+)\1)

Hãy thử nó ở đây.

Giải trình

^(?!.*                    # Match a string that doesn't contain the pattern,
                          # at any position.
  (?=(.))                 # Capture the next character.
  (
    (.{9})+               # Any 9*n characters. The next character is in
                          # the same column as the captured one.
  |
    (.(?!(.{9})*$))+      # Any n characters not followed by a positions 9*m
                          # to the end. The next character is in the same row
                          # as the captured one.
  |
    (                     # Any n occasions of...
    ?(.(...)*$)           # If it is at a position 3*k+1 to the end:
      (.(?!(.{27})*$)){7} # Then count 7*m characters that are not followed
                          # by a position 27*j to the end,
    |
      .                   # Else count any character.
    )+                    # The next character is in the same block as the
                          # captured one.
  )
  \1                      # Fail if the next character is the captured character.
)

Wow công việc tốt. Tôi chỉ nhận được nó thành 83 trong .NET và phải chuyển sang PCRE cho 78. Tôi không nghi ngờ gì nữa, cuối cùng bạn cũng sẽ đánh bại nó. :)
Martin Ender

@ MartinBüttner Yep.
Nic Hartley

Tôi nghĩ rằng việc tôi sử dụng lookahead để đánh bại @ MartinBüttner bởi (vào thời điểm đó) 4 byte là gọn gàng nhưng bạn đã đưa nó lên cấp độ tiếp theo.
Neil

Xin lỗi, nhưng điều này không phát hiện xem các ô ở (1, 2) và (2, 1) có giống nhau hay không, và tương tự cho tất cả các ô khác trong các ô vuông có trùng lặp bên dưới và bên trái.
Neil

1
@ MartinBüttner Tôi mới nhận ra rằng tôi có thể dịch phiên bản PCRE thứ hai của mình sang Ruby ... Tôi đoán bạn có thể đăng câu trả lời của mình ngay bây giờ ...
jimmy23013

34

PCRE, 117 119 130 133 147 byte

^(?!(.{27})*(...){0,2}(.{9})?.?.?(.).?.?(?=(?2)*$).{6,8}(?3)?\4.{0,17}(?1)*$|.*(.)(.{8}(?3)*|((?!(?3)*$)(|.(?7))))\5)

Cũng nên làm việc trong các hương vị Python, Java, v.v. Bây giờ với đệ quy! Và tính năng "đệ quy" được sử dụng không đệ quy cho "chương trình con", điều mà tôi hoàn toàn quên mất cho đến khi tôi phải sử dụng đệ quy thực tế.


Ý tưởng tuyệt vời - tránh lặp lại thay vì phù hợp với norepeats!
Qwertiy

1
Thật xấu hổ bạn không thể viết .{27}*.
Neil

Bah, tôi đã đánh golf giải pháp 133 byte của bạn xuống còn 121 byte chỉ để thấy rằng bạn đã viết lại nó, nhưng dù sao thì đây là:^(?!(.{27})*(.{9})?(...){0,2}.?.?(.).?.?(?=(...)*$)(.{9})?.{6,8}\4.{0,17}(.{27})*$|.*(.)((.{9})+|((?!(.{9})*$).)+)(<=\8))
Neil

@Neil Hương vị gì vậy? PCRE hoặc những người khác mà tôi biết không cho phép phản hồi trong một diện mạo.
frageum

@Neil (<=\8)không giống như cú pháp hợp lệ (nó thiếu a ?). Ngoài ra, hương vị duy nhất tôi biết hỗ trợ phản hồi trong lookbehinds là .NET.
Martin Ender

15

.NET regex, 8339 byte

Vâng, tôi biết giải pháp của tôi rất ngây thơ, vì Martin nói với tôi rằng anh ấy đã làm nó trong khoảng 130 byte. Trên thực tế, URL để dùng thử trực tuyến quá dài đến nỗi tôi không thể tìm thấy trình rút ngắn URL nào có thể chấp nhận nó.

(code removed, since it's so long nobody will read it here, 
and it made the post take forever to load. Just use the "Try it online" link.)

Liên kết dưới đây không hoạt động trong IE, nhưng hoạt động trong Chrome và Firefox.

Dùng thử trực tuyến - Tất cả các trường hợp thử nghiệm cùng một lúc, với sự trợ giúp của!`lúc đầu, không bao gồm trong số byte.


Đây là tập lệnh Python tôi đã sử dụng để tạo nó (mã bên dưới):

R=range(0,9)
S=range(1,10)

o = ""

# validate rows
T = "(?=.{%s,%s}%s)"
for j in R:
    for i in S:
        o += T % (9*j,9*(j+1)-1, i)

# validate columns
# "(?=(.{%s}|.{%s}|.{%s}|.{%s}|.{%s}|.{%s}|.{%s}|.{%s}|.{%s})%s)"
T = "(?=("+"|".join([".{%s}"]*9)+")%s)"
for j in R:
    for i in S:
        o += T % (j,j+9,j+18,j+27,j+36,j+45,j+54,j+63,j+72, i)

# validate boxes
# (?=.{0,2}1|.{9,11}1|.{18,20}1)(?=.{3,5}1|.{12,14}1|.{21,23}1)
# (?=.{27,29}1|.{36,38}1|.{45,47}1)
T = ".{%s,%s}%s"
for i in S:
    for x in (0,27,54):
        for y in (0,3,6):
            o += "(?="+"|".join(T % (x+y+z,x+y+z+2, i) for z in (0,9,18))+")"

o += ".{81}"

o = o.replace(".{0}","").replace(",80}",",}")
print(o)

1
Tôi đang root cho bạn
Martijn

4
Biết những gì buồn cười? Liên kết dùng thử trực tuyến sẽ sập IE vì quá dài: P
cat

15
@cat Đó là lý do tại sao mục đích thực sự duy nhất của IE là cho phép người dùng tải xuống Firefox (hoặc Chromium).
Chỉ huy Byte

2
@cat Nó không sập IE11 trên Windows 8.1, mặc dù Regex không được xử lý đúng cách.
Nzall

2
@cat Nó không sập IE 11 của tôi trên Windows 7. Nó chỉ cắt bớt URL.
mbomb007

14

.NET regex, 121 byte

^(?!(.{27})*(.{9})?(...){0,2}.?.?(.).?.?(?=(...)*$)(.{9})?.{6,8}\4.{0,17}(.{27})*$|.*(?=(.))((.{9})+|(.(?!(.{9})*$))+)\8)

Giải trình:

^(?!                     Invert match (because we're excluding duplicates)
 (.{27})*                Skip 0, 3 or 6 rows
 (.{9})?                 Optionally skip another row
 (...){0,2}              Skip 0, 3 or 6 columns
 .?.?(.).?.?(?=(...)*$)  Choose any of the next three cells
 (.{9})?                 Optionally skip another row
 .{6,8}\4                Match any of the three cells below
 .{0,17}(.{27})*$        As long as they're from the same square
|                        OR
 .*(?=(.))(              Choose any cell
  (.{9})+                Skip at least one row
 |                       or
  (.                     Skip cells
   (?!(.{9})*$)          Without reaching the end of the row
  )+                     For at least one cell (i.e. the cell chosen above)
 )\8)                    Match the chosen cell to the next cell
)

Đẹp, sự kết hợp của các hàng và cột của bạn là khá thông minh. Điều đó tiết kiệm 4 byte trên giải pháp của riêng tôi. :)
Martin Ender

8

PCRE, 3579 byte

Một giải pháp vũ phu hoàn toàn khủng khiếp. Cái nhìn tiêu cực ahoy!

Tôi đã dành quá nhiều thời gian cho việc này để từ bỏ nó, vì vậy đây là vì lợi ích của hậu thế.

Về mặt sáng sủa, nếu Sudoku đột nhiên bắt đầu sử dụng một bộ 9 ký tự khác, thì điều này vẫn sẽ hoạt động, tôi đoán ...

http://pastebin.com/raw/CwtviGkC

Tôi không biết cách vận hành Retina, nhưng bạn cũng có thể dán nó vào https://regex101.com hoặc tương tự và nó sẽ khớp.

Mã Ruby được sử dụng để tạo regex:

# Calculate the block you're in
def block(x)
    x /= 3
    x + x%3 - x%9
end

81.times do |i|
    row, col = i.divmod(9)
    neg = []
    neg += (0...col).map {|e| 9*row + e + 1}
    neg += (0...row).map {|e| 9*e + col + 1}
    neg += (0...i).map {|e| e + 1 if block(e) == block(i)}.compact
    neg = neg.uniq.sort.map {|e| "\\#{e}"}
    if neg.size > 0
        print "(?!#{neg.join '|'})"
    end
    print "(.)"
end

8

Hương vị Ruby, 75 74 byte

Cảm ơn jimmy23013 vì đã tiết kiệm 1 byte.

^(?!(.{9}*(.|(.)){,8}|.*(\g<2>.{8})*|.{27}?.{3}?(\g<2>{3}.{6}){,2}.?.?)\3).

Kiểm tra nó ở đây.

Bây giờ nó cuối cùng đã bị đánh bại, tôi có thể chia sẻ giải pháp của riêng mình. :) Tôi đã phát hiện ra một kỹ thuật regex thú vị (có thể là mới?) Trong quy trình ( (.|(.)){,8}\3phần), có thể là không thể đánh bại trong trường hợp không thể kết hợp với các phần khác của regex (như trường hợp trong câu trả lời của jimmy23013) .

Giải trình

Giống như các câu trả lời ngắn khác, tôi đang sử dụng một cái nhìn tiêu cực để tìm kiếm các bản sao trong các hàng, cột hoặc khối. Khối xây dựng cơ bản của giải pháp là:

(.|(.))...\3

Lưu ý rằng \3được sử dụng lại giữa ba lựa chọn thay thế khác nhau (tất cả đều sử dụng nhóm 3để phát hiện trùng lặp).

Nhóm đó ở bên trái (là nhóm 2, chứa nhóm 3) được sử dụng cho bất kỳ vị trí nào có thể chứa nửa đầu của một chữ số trùng lặp (trong một nhóm không được chứa các chữ số trùng lặp). Sau đó, ...một cái gì đó đưa chúng ta đến vị trí tiếp theo nơi một chữ số như vậy có thể xảy ra (nếu cần thiết) và \3cố gắng tìm nửa sau của bản sao thông qua phản hồi. Lý do công việc này là quay lại. Khi động cơ đầu tiên phù hợp, (.|(.))nó sẽ chỉ sử dụng .mọi lúc và không chụp bất cứ thứ gì. Bây giờ \3cuối cùng thất bại. Nhưng bây giờ, động cơ sẽ dần dần thử sử dụng (.)thay vì .cho các trận đấu riêng lẻ. Cuối cùng, nếu có một bản sao, nó sẽ tìm thấy sự kết hợp trong đó(.)được sử dụng lần cuối trên chữ số đầu tiên của bản sao (sao cho bản chụp không bị ghi đè sau này), và sau đó sử dụng một số chi tiết khác .để thu hẹp khoảng cách đến mức phản hồi. Nếu có một bản sao, quay lui sẽ luôn tìm thấy nó.

Hãy xem xét ba phần khác nhau nơi sử dụng:

.{9}*(.|(.)){,8}

Điều này kiểm tra các bản sao trong một số hàng. Đầu tiên chúng ta bỏ qua bất kỳ hàng nào với .{9}*. Sau đó, chúng tôi khớp tối đa 8 ký tự (nghĩa là bất kỳ thứ gì trong hàng đó ngoại trừ chữ số cuối cùng) bằng cách sử dụng bản sao trùng lặp tùy chọn và cố gắng tìm \3sau nó.

.*(\g<2>.{8})*

Điều này tìm kiếm các bản sao trong một số cột. Đầu tiên, lưu ý rằng đó \g<2>là một cuộc gọi chương trình con, vì vậy đây là giống như:

.*((.|(.)).{8})*

trong đó hai nhóm chúng ta vừa chèn vẫn được gọi là 23.

Ở đây, .*chỉ cần bỏ qua khi cần thiết (nó sẽ đủ để khớp tối đa 8 ký tự ở đây, nhưng chi phí nhiều byte hơn). Sau đó, nhóm bên ngoài khớp với một hàng hoàn chỉnh (có thể bao quanh hai hàng vật lý) tại một thời điểm, tùy ý bắt ký tự đầu tiên. Các \3sẽ được xem xét cho đúng sau này, đảm bảo sự liên kết dọc giữa việc bắt giữ và backreference.

Cuối cùng, kiểm tra các khối:

.{27}?.{3}?(\g<2>{3}.{6}){,2}.?.?

Một lần nữa, đó \g<2>là một cuộc gọi chương trình con, vì vậy đây là giống như:

.{27}?.{3}?((.|(.)){3}.{6}){,2}.?.?

Để xác minh các khối, lưu ý rằng vì chúng tôi đã kiểm tra tất cả các hàng và cột, chúng tôi chỉ cần kiểm tra bốn trong số các khối 3x3. Khi chúng ta biết rằng tất cả các hàng và cột cũng như các khối 3x3 này đều đúng:

XX.
XX.
...

Sau đó, chúng ta biết rằng không thể có sự trùng lặp trong các khối còn lại. Do đó tôi chỉ kiểm tra bốn khối này. Hơn nữa, lưu ý rằng chúng ta không phải tìm kiếm các bản sao trong cùng một hàng của khối 3x3. Đủ để tìm nửa đầu của bản sao trong một hàng và tìm kiếm nửa sau liên tiếp xuống.

Bây giờ đối với bản thân mã, trước tiên chúng ta bỏ qua phần đầu của một trong bốn khối với .{27}?.{3}?(tùy ý bỏ qua ba hàng, tùy ý bỏ qua ba cột). Sau đó, chúng tôi cố gắng khớp tối đa hai trong số các hàng của khối 3x3 với cùng một mẹo mà chúng tôi đã sử dụng cho các hàng trước đó:

(.|(.)){3}.{6}

Chúng tôi cho phép nhưng không yêu cầu bắt giữ bất kỳ 3 ô nào trong hàng hiện tại của khối 3x3 và sau đó chuyển sang hàng tiếp theo với .{6}. Cuối cùng, chúng tôi cố gắng tìm một bản sao trong một trong 3 ô của hàng mà chúng tôi kết thúc:

.?.?

Và đó là nó.


74 : ^(?!(.*((.|(.)).{8})*|.{9}*\g<3>{,8}|.{27}?.{3}?(\g<3>{3}.{6}){,2}.?.?)\4); 73 : ^(?!(.*((.|(.)|\4()).{8})*|.{9}*\g<3>{9}|.{27}?.{3}?(\g<3>{3}.{6}){3})\5).
jimmy23013

@ jimmy23013 Tôi thực sự đã sử dụng \4()thủ thuật trong phiên bản trước đó cho các khối 3x3, nhưng cuối cùng đã thoát khỏi nó, vì nó dài hơn. : D
Martin Ender

@ jimmy23013 73 người không kiểm tra hàng cuối cùng:341572689257698143986413275862341957495726831173985426519234768734869512628517394
Martin Ender

6

Javascript regex, 532 530 481 463 chars

Xác thực hàng:

/^((?=.{0,8}1)(?=.{0,8}2)(?=.{0,8}3)(?=.{0,8}4)(?=.{0,8}5)(?=.{0,8}6)(?=.{0,8}7)(?=.{0,8}8)(?=.{0,8}9).{9})+$/

Xác thực cột:

/^((?=(.{9}){0,8}1)(?=(.{9}){0,8}2)(?=(.{9}){0,8}3)(?=(.{9}){0,8}4)(?=(.{9}){0,8}5)(?=(.{9}){0,8}6)(?=(.{9}){0,8}7)(?=(.{9}){0,8}8)(?=(.{9}){0,8}9).){9}/

Xác thực hình vuông từ char đầu tiên của nó:

/(?=.?.?(.{9}){0,2}1)(?=.?.?(.{9}){0,2}2)(?=.?.?(.{9}){0,2}3)(?=.?.?(.{9}){0,2}4)(?=.?.?(.{9}){0,2}5)(?=.?.?(.{9}){0,2}6)(?=.?.?(.{9}){0,2}7)(?=.?.?(.{9}){0,2}8)(?=.?.?(.{9}){0,2}9)/

Đặt chế độ xem trước để bắt đầu hình vuông:

/^(((?=)...){3}.{18})+$/

Và toàn bộ biểu thức:

/^(?=((?=.{0,8}1)(?=.{0,8}2)(?=.{0,8}3)(?=.{0,8}4)(?=.{0,8}5)(?=.{0,8}6)(?=.{0,8}7)(?=.{0,8}8)(?=.{0,8}9).{9})+$)(?=((?=(.{9}){0,8}1)(?=(.{9}){0,8}2)(?=(.{9}){0,8}3)(?=(.{9}){0,8}4)(?=(.{9}){0,8}5)(?=(.{9}){0,8}6)(?=(.{9}){0,8}7)(?=(.{9}){0,8}8)(?=(.{9}){0,8}9).){9})(((?=.?.?(.{9}){0,2}1)(?=.?.?(.{9}){0,2}2)(?=.?.?(.{9}){0,2}3)(?=.?.?(.{9}){0,2}4)(?=.?.?(.{9}){0,2}5)(?=.?.?(.{9}){0,2}6)(?=.?.?(.{9}){0,2}7)(?=.?.?(.{9}){0,2}8)(?=.?.?(.{9}){0,2}9)...){3}.{18})+$/

Phù hợp với toàn bộ chuỗi.


Kiểm tra trong Javascript ES6:

r = /^(?=((?=.{0,8}1)(?=.{0,8}2)(?=.{0,8}3)(?=.{0,8}4)(?=.{0,8}5)(?=.{0,8}6)(?=.{0,8}7)(?=.{0,8}8)(?=.{0,8}9).{9})+$)(?=((?=(.{9}){0,8}1)(?=(.{9}){0,8}2)(?=(.{9}){0,8}3)(?=(.{9}){0,8}4)(?=(.{9}){0,8}5)(?=(.{9}){0,8}6)(?=(.{9}){0,8}7)(?=(.{9}){0,8}8)(?=(.{9}){0,8}9).){9})(((?=.?.?(.{9}){0,2}1)(?=.?.?(.{9}){0,2}2)(?=.?.?(.{9}){0,2}3)(?=.?.?(.{9}){0,2}4)(?=.?.?(.{9}){0,2}5)(?=.?.?(.{9}){0,2}6)(?=.?.?(.{9}){0,2}7)(?=.?.?(.{9}){0,2}8)(?=.?.?(.{9}){0,2}9)...){3}.{18})+$/
;`123456789456789123789123456231564897564897231897231564312645978645978312978312645
725893461841657392396142758473516829168429537952378146234761985687935214519284673
395412678824376591671589243156928437249735186738641925983164752412857369567293814
679543182158926473432817659567381294914265738283479561345792816896154327721638945
867539142324167859159482736275398614936241587481756923592873461743615298618924375
954217683861453729372968145516832497249675318783149256437581962695324871128796534
271459386435168927986273541518734269769821435342596178194387652657942813823615794
237541896186927345495386721743269158569178432812435679378652914924813567651794283
168279435459863271273415986821354769734692518596781342615947823387526194942138657
863459712415273869279168354526387941947615238138942576781596423354821697692734185
768593142423176859951428736184765923572389614639214587816942375295837461347651298`
.split`
`.every(r.test.bind(r))
&&
`519284673725893461841657392396142758473516829168429537952378146234761985687935214
839541267182437659367158924715692843624973518573864192298316475941285736456729381
679543182158926473432817659567381294914256738283479561345792816896154327721638945
867539142324167859159482736275398684936241517481756923592873461743615298618924375
754219683861453729372968145516832497249675318983147256437581962695324871128796534
271459386435168927986273541518734269769828435342596178194387652657942813823615794
237541896186927345378652914743269158569178432812435679495386721924813567651794283
168759432459613278273165984821594763734982516596821347615437829387246195942378651
869887283619214453457338664548525781275424668379969727517385163319223917621449519
894158578962859187461322315913849812241742157275462973384219294849882291119423759
123456789456789123564897231231564897789123456897231564312645978645978312978312645
145278369256389147364197258478512693589623471697431582712845936823956714931764825`
.split`
`.every(s => !r.test(s))

Tôi nghĩ rằng các cột nên dễ dàng hơn nhiều so với các hàng, vì vậy tôi thấy tò mò rằng regex cột của bạn dài hơn hàng của bạn.
Peter Taylor

@PeterTaylor, chúng có cùng cấu trúc, nhưng đối với các cột tôi phải bỏ qua 9 ký tự thay vì 1, vì vậy .phải nhập vào (.{9})dấu ngoặc vì tiếp theo {0,8}. Tại sao bạn nghĩ rằng cột nên ngắn hơn?
Qwertiy

@PeterTaylor, yep, các cột sẽ đơn giản hơn nếu tôi đoán kiểm tra phủ định.
Qwertiy

@ SuperJedi224, tại sao javascript? Tôi hy vọng regex này có giá trị ở mọi nơi.
Qwertiy

6
@Qwertiy Mặc dù regex của bạn nên hoạt động theo nhiều hương vị, nhưng nó phụ thuộc vào lookahead (chẳng hạn như có sẵn trong Lua hoặc OCaml). Nó cũng là một biểu thức chính quy cơ bản hoặc mở rộng không hợp lệ, sử dụng một cú pháp hoàn toàn khác. Tốt nhất là chọn hương vị cho yêu cầu hợp lệ, ngay cả khi giải pháp hoạt động ở nhiều người khác.
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.