Regex 🐇
(Perl / PCRE), 160 147 bytes
^(?(?=-x*,(?!-))-?+x*(,x*(?!$))?|-?(?=(x*),-?(x*))(?=(x*),?(?=\2)(?=\3)(x*,-?|[^,]*)(x*))\4,?+x*)(?!((?=(x+)(\8{9}x*))\9)*(x{10})*x{5}\b)(?(4)\4\6)
Try it online! - Perl
Try it online! - PCRE (faster)
Takes its input in unary, as two strings of x
characters whose lengths represent the numbers, with optional -
signs on their left side, joined by a ,
delimiter. Returns its output as the number of ways the regex can match. (The rabbit emoji indicates this output method.)
Most of the logic of this regex is taken up with handling the logic of integer ranges. It's rather unnatural... literally. Natural numbers (including zero) are much easier for a regex to operate on.
^
(?(?=-x*,(?!-))
# Do the following if A is negative and B is nonnegative
-?+ # skip sign of A, if any
x* # handle the range from larger to zero, inclusive
(,x*(?!$))? # handle the range from B inclusive to zero exclusive
|
# Do the following if A is nonnegative or B is negative
-? # skip sign of A, if any
(?=
(x*), # \2 = abs(A);
-?(x*) # \3 = abs(B)
)
(?=
(x*),?(?=\2)(?=\3) # \4 = what to skip so tail = the larger of A or B;
# tail = the larger of A or B
(x*,-?|[^,]*)(x*) # \6 = {the smaller of A or B} - \4
)
\4,?+ # tail = the larger of A or B
x* # handle the range from larger to {smaller or zero}
)
(?! # Negative lookahead - assert this can't match
(
(?=(x+)(\8{9}x*)) # \8 = floor(tail / 10); \9 = tail - \8
\9 # tail = tail - \9 == \8
)* # Iterate the above any number of times, minimum zero
(x{10})*x{5}\b # Assert tail % 10 == 5
)
(?(4)\4\6) # If \4 is set, clamp the range at the smaller end
It uses conditionals, which are not supported by ECMAScript, but it'd be easy enough to port (though the regex would be even longer). The 🐇
output method is required for this algorithm to be possible in ECMAScript (there isn't yet a regex engine that can emulate ECMAScript and count possible matches, but I'm planning on adding this to RegexMathEngine soon).
Regex (.NET), 163 bytes
^(?=(-x*,(?!-))?)(?>-?)(?(1)|(?=(x*),-?(x*))(?=(x*),?(?=\2)(?=\3)(x*,-?|[^,]*)(x*))\4(?>,?))(?(,)(?(1),)|(?(((?=(x+)(\8{9}x*))\9)*(x{10})*x{5}\b)|())x?)*(?(4)\4\6)
Try it online!
Returns its output as the capture count of group \11
.
^
(?=
(-x*,(?!-))? # \1 = set iff A is negative and B is nonnegative
)
(?>-?) # skip sign of A, if any
(?(1)
|
# Do the following if A is nonnegative or B is negative
(?=
(x*), # \2 = abs(A);
-?(x*) # \3 = abs(B)
)
(?=
(x*),?(?=\2)(?=\3) # \4 = what to skip so tail = the larger of A or B;
# tail = the larger of A or B
(x*,-?|[^,]*)(x*) # \6 = {the smaller of A or B} - \4
)
\4 # tail = the larger of A or B
(?>,?) # skip sign of B, if any
)
# First handle the range from larger inclusive to
# {smaller inclusive or 0 exclusive}
(?(,)
(?(1),) # If crossing from negative to nonnegative, handle
# the inclusive range from B to 0
|
(?(
(
(?=(x+)(\8{9}x*)) # \8 = floor(tail / 10); \9 = tail - \8
\9 # tail = tail - \9 == \8
)* # Iterate the above any number of times
(x{10})*x{5}\b # Assert tail % 10 == 5
)
|
() # Push a capture onto the \11 stack
)
x? # Advance by 1, but if already at the end, allow the
# loop to iterate once more so as to include 0 in
# the count.
)*
(?(4)\4\6) # If \4 is set, clamp the range at the smaller end
It could also be ported to an output method of the sum of the lengths of two capture groups (two, because the output can exceed the largest of the two inputs), though this would probably make it significantly longer.
50, 59 -> 0
. \$\endgroup\$