Regex Golf: Verify a Sudoku Solution
Ruby regex, 71 78 73 bytes
^(?!.*(?=(.))(.{9}+|(.(?!.{9}*$))+|(?>.(?!.{3}*$)|(.(?!.{27}*$)){7})+)\1)
I don't really know Ruby but apparently it doesn't complain about cascaded quantifiers.
Try it here.
.NET regex, 79 78 75 or 77 bytes
Because Martin thinks this is possible... But I guess he will just incorporate these changes too.
^(?!(.)+((.{9})+|(?>(.{9})+
|.)+|(?((...)*
)(?>(.{27})+
|.){7}|.)+)(?<=\1))
Requires a trailing newline in the input to work. I'm not sure whether I'm allowed to do this (probably not).
Try it here.
The 77 byte sane version:
^(?!(.)+((.{9})+|((?!(.{9})*$).)+|(?((...)*$)((?!(.{27})*$).){7}|.)+)(?<=\1))
Thanks Neil for pointing out the error in my previous version and golfing off 1 byte (for the (...)*
).
Try it here.
PCRE, 77 78 bytes
^(?!.*(?=(.))((.{9})+|(.(?!(?3)*$))+|(?(?=.(...)*$)(.(?!(.{27})*$)){7}|.)+)\1)
Just for completeness.
Try it here.
Another version, also 78 bytes:
^(?!.*(?=(.))((.{9})+|(.(?!(?3)*$))+|(?>.(?!(...)*$)|(.(?!(.{27})*$)){7})+)\1)
Try it here.
Explanation
^(?!.* # 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.
)
PCRE, 117 119 130 133 147 bytes
^(?!(.{27})*(...){0,2}(.{9})?.?.?(.).?.?(?=(?2)*$).{6,8}(?3)?\4.{0,17}(?1)*$|.*(.)(.{8}(?3)*|((?!(?3)*$)(|.(?7))))\5)
Should also work in Python, Java, etc. flavors. Now with recursion! And the "recursion" feature used non-recursively for "subroutines", which I totally forgot about until I had to use actual recursion.
.NET regex, 8339 bytes
Yes, I know my solution is very naive, since Martin told me he did it in like 130 bytes. In fact, the URL to try it online is so long that I couldn't find a URL shortener that would accept it.
(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.)
The below link does not work in IE, but does work in Chrome and Firefox.
Try it online - All test cases at once, with the help of !`
at the beginning, not included in byte count.
Here's the Python script I used to generate it (code below):
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)